lua: add lua engine to process internal logic
[profile/tv/apps/native/screen-reader.git] / src / lua_engine.c
1 #include <lua.h>
2 #include <lauxlib.h>
3 #include <lualib.h>
4
5 #include <stdlib.h>
6 #include <stdio.h>
7
8 #include "logger.h"
9 #include "lua_engine.h"
10
11 #include <string.h>
12
13 #define ACCESSIBLE_CLASS_NAME "Accessible"
14 #define VALUE_CLASS_NAME "Value"
15 #define SELECTION_CLASS_NAME "Selection"
16
17 #define GERROR_CHECK(err) \
18         if (err) { lua_error(L); printf("GError: %s\n", err->message); g_error_free(err); }
19
20 static lua_State *L;
21
22
23 static void *_pop_class_obj(lua_State *L, int index, int narg, const char *class)
24 {
25         luaL_checktype(L, narg, LUA_TUSERDATA);
26         void **ret = lua_touserdata(L, index);
27         if (!ret) luaL_typerror(L, narg, class);
28         return *ret;
29 }
30
31 static void _push_class_obj(lua_State *L, void *obj, const char *class)
32 {
33         void **ptr = lua_newuserdata(L, sizeof(void*));
34         *ptr = obj;
35         luaL_getmetatable(L, class);
36         lua_setmetatable(L, -2);
37 }
38
39 static int _accessible_name(lua_State *L) {
40         AtspiAccessible *obj = _pop_class_obj(L, -1, 1, ACCESSIBLE_CLASS_NAME);
41         GError *err = NULL;
42         if (!obj) return 0;
43
44         char *name = atspi_accessible_get_name(obj, &err);
45         GERROR_CHECK(err);
46
47         lua_pushstring(L, name);
48         g_free(name);
49         return 1;
50 }
51
52 static int _accessible_description(lua_State *L) {
53         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
54         GError *err = NULL;
55         if (!obj)
56                 return 0;
57         char *name = atspi_accessible_get_description(obj, &err);
58         GERROR_CHECK(err);
59
60         lua_pushstring(L, name);
61         g_free(name);
62         return 1;
63 }
64
65 static int l_get_root(lua_State *L) {
66         AtspiAccessible *root = atspi_get_desktop(0);
67         _push_class_obj(L, root, ACCESSIBLE_CLASS_NAME);
68         return 1;
69 }
70
71 static int l_get_translation(lua_State *L) {
72         const char *str = lua_tostring(L, -1);
73         lua_pushstring(L, _(str));
74         return 1;
75 }
76
77 static int _accessible_children(lua_State *L) {
78         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
79         GError *err = NULL;
80         if (!obj)
81                 return 0;
82         int i, n = atspi_accessible_get_child_count(obj, &err);
83         GERROR_CHECK(err);
84
85         lua_createtable(L, n, 0);
86
87         for (i = 0; i < n; i++)
88         {
89                 AtspiAccessible *child = atspi_accessible_get_child_at_index(obj, i, &err);
90                 if (!child) continue;
91                 GERROR_CHECK(err);
92                 lua_pushinteger(L, i + 1);
93                 _push_class_obj(L, child, ACCESSIBLE_CLASS_NAME);
94                 lua_settable(L, -3);
95         }
96         return 1;
97 }
98
99 static int _accessible_parent(lua_State *L) {
100         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
101         GError *err = NULL;
102         if (!obj) return 0;
103
104         AtspiAccessible *parent = atspi_accessible_get_parent(obj, &err);
105         if (!parent) return 0;
106         GERROR_CHECK(err);
107         _push_class_obj(L, parent, ACCESSIBLE_CLASS_NAME);
108
109         return 1;
110 }
111
112 static int _accessible_role(lua_State *L) {
113         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
114         GError *err = NULL;
115         if (!obj) return 0;
116
117         AtspiRole role = atspi_accessible_get_role(obj, &err);
118         GERROR_CHECK(err);
119
120         lua_pushinteger(L, role);
121
122         return 1;
123 }
124
125 static int _accessible_role_name(lua_State *L) {
126         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
127         GError *err = NULL;
128         if (!obj) {
129                 return 0;
130         }
131         char *name = atspi_accessible_get_localized_role_name(obj, &err);
132         GERROR_CHECK(err);
133
134         lua_pushstring(L, name);
135         g_free(name);
136         return 1;
137 }
138
139 static int _accessible_is(lua_State *L) {
140         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
141         AtspiStateType type = lua_tonumber(L, -1);
142
143         AtspiStateSet *ss = atspi_accessible_get_state_set(obj);
144
145         if (atspi_state_set_contains(ss, type))
146                 lua_pushboolean(L, 1);
147         else
148                 lua_pushboolean(L, 0);
149
150         return 1;
151 }
152
153 static int _accessible_index(lua_State *L) {
154         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
155         GError *err = NULL;
156         if (!obj) return 0;
157
158         int idx = atspi_accessible_get_index_in_parent(obj, &err);
159         GERROR_CHECK(err);
160
161         lua_pushinteger(L, idx);
162         return 1;
163 }
164
165 static int _accessible_relations(lua_State *L) {
166         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
167         AtspiRelationType type = lua_tonumber(L, -1);
168         GError *err = NULL;
169         int i, j;
170
171         lua_newtable(L);
172         if (!obj) return 1;
173         GArray *rels = atspi_accessible_get_relation_set(obj, &err);
174         GERROR_CHECK(err);
175         if (!rels) return 1;
176
177         for (i = 0; i < rels->len; i++)
178         {
179                 AtspiRelation *rel = g_array_index(rels, AtspiRelation*, i);
180                 if (atspi_relation_get_relation_type(rel) == type)
181                 {
182                         for (j = 0; j < atspi_relation_get_n_targets(rel); j++)
183                         {
184                                 AtspiAccessible *target = atspi_relation_get_target(rel, j);
185                                 if (!target) continue;
186                                 lua_pushinteger(L, j);
187                                 _push_class_obj(L, target, ACCESSIBLE_CLASS_NAME);
188                                 lua_settable(L, -3);
189                         }
190                 }
191                 g_object_unref(rel);
192         }
193         g_array_free(rels, TRUE);
194
195         return 1;
196 }
197
198 static int _accessible_value(lua_State *L) {
199         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
200         AtspiValue *val = atspi_accessible_get_value_iface(obj);
201         if (!val)
202         {
203                 lua_pushnil(L);
204                 return 1;
205         }
206         _push_class_obj(L, val, VALUE_CLASS_NAME);
207         return 1;
208 }
209
210 static int _accessible_selection(lua_State *L) {
211         AtspiAccessible *obj = _pop_class_obj(L, 1, 1, ACCESSIBLE_CLASS_NAME);
212         AtspiSelection *sel = atspi_accessible_get_selection_iface(obj);
213         if (!sel)
214         {
215                 lua_pushnil(L);
216                 return 1;
217         }
218         _push_class_obj(L, sel, SELECTION_CLASS_NAME);
219         return 1;
220 }
221
222 static int _gobject_unref(lua_State *L) {
223 #ifdef SCREEN_READER_FLAT_NAVI_TEST_DUMMY_IMPLEMENTATION
224         return 0;
225 #else
226         void **ret = lua_touserdata(L, -1);
227         g_object_unref(*ret);
228         return 0;
229 #endif
230 }
231
232 static const luaL_reg _meta_methods[] = {
233         { "__gc", _gobject_unref},
234         { NULL, NULL}
235 };
236
237 static const luaL_reg _accessible_methods[] = {
238         { "name", _accessible_name },
239         { "description", _accessible_description },
240         { "children", _accessible_children },
241         { "parent", _accessible_parent },
242         { "role", _accessible_role },
243         { "inRelation", _accessible_relations },
244         { "roleName", _accessible_role_name },
245         { "is", _accessible_is },
246         { "index", _accessible_index },
247         { "value", _accessible_value },
248         { "selection", _accessible_selection },
249         { NULL, NULL}
250 };
251
252 static int _value_current_value(lua_State *L) {
253         AtspiValue *val = _pop_class_obj(L, -1, 1, VALUE_CLASS_NAME);
254         GError *err = NULL;
255
256         double cv = atspi_value_get_current_value(val, &err);
257         GERROR_CHECK(err);
258
259         lua_pushnumber(L, cv);
260
261         return 1;
262 }
263
264 static int _value_range(lua_State *L) {
265         AtspiValue *val = _pop_class_obj(L, -1, 1, VALUE_CLASS_NAME);
266         GError *err = NULL;
267         double max, min;
268
269         max = atspi_value_get_maximum_value(val, &err);
270         GERROR_CHECK(err);
271
272         min = atspi_value_get_minimum_value(val, &err);
273         GERROR_CHECK(err);
274
275         lua_pushnumber(L, min);
276         lua_pushnumber(L, max);
277
278         return 2;
279 }
280
281 static int _value_increment(lua_State *L) {
282         AtspiValue *val = _pop_class_obj(L, 1, 1, VALUE_CLASS_NAME);
283         GError *err = NULL;
284
285         double mi = atspi_value_get_minimum_increment(val, &err);
286         GERROR_CHECK(err);
287
288         lua_pushnumber(L, mi);
289
290         return 1;
291 }
292
293 static const luaL_reg _value_methods[] = {
294         { "current", _value_current_value },
295         { "range", _value_range },
296         { "increment", _value_increment },
297         { NULL, NULL}
298 };
299
300 static int _selection_is_selected(lua_State *L) {
301         AtspiSelection *sel = _pop_class_obj(L, 1, 1, SELECTION_CLASS_NAME);
302         GError *err = NULL;
303         int id = lua_tointeger(L, -1);
304
305         gboolean ret = atspi_selection_is_child_selected(sel, id, &err);
306         GERROR_CHECK(err);
307
308         lua_pushboolean(L, ret);
309
310         return 1;
311 }
312
313 static int _selection_count(lua_State *L) {
314         AtspiSelection *sel = _pop_class_obj(L, 1, 1, SELECTION_CLASS_NAME);
315         GError *err = NULL;
316
317         int mi = atspi_selection_get_n_selected_children(sel, &err);
318         GERROR_CHECK(err);
319
320         lua_pushinteger(L, mi);
321
322         return 1;
323 }
324
325 static const luaL_reg _selection_methods[] = {
326         { "count", _selection_count },
327         { "isSelected", _selection_is_selected },
328         { NULL, NULL}
329 };
330
331 static void _register_role_enums(lua_State *L)
332 {
333         lua_pushinteger(L, ATSPI_ROLE_INVALID);
334         lua_setglobal(L, "INVALID");
335         lua_pushinteger(L, ATSPI_ROLE_ACCELERATOR_LABEL);
336         lua_setglobal(L, "ACCELERATOR_LABEL");
337         lua_pushinteger(L, ATSPI_ROLE_ALERT);
338         lua_setglobal(L, "ALERT");
339         lua_pushinteger(L, ATSPI_ROLE_ANIMATION);
340         lua_setglobal(L, "ANIMATION");
341         lua_pushinteger(L, ATSPI_ROLE_ARROW);
342         lua_setglobal(L, "ARROW");
343         lua_pushinteger(L, ATSPI_ROLE_CALENDAR);
344         lua_setglobal(L, "CALENDAR");
345         lua_pushinteger(L, ATSPI_ROLE_CANVAS);
346         lua_setglobal(L, "CANVAS");
347         lua_pushinteger(L, ATSPI_ROLE_CHECK_BOX);
348         lua_setglobal(L, "CHECK_BOX");
349         lua_pushinteger(L, ATSPI_ROLE_CHECK_MENU_ITEM);
350         lua_setglobal(L, "CHECK_MENU_ITEM");
351         lua_pushinteger(L, ATSPI_ROLE_COLOR_CHOOSER);
352         lua_setglobal(L, "COLOR_CHOOSER");
353         lua_pushinteger(L, ATSPI_ROLE_COLUMN_HEADER);
354         lua_setglobal(L, "COLUMN_HEADER");
355         lua_pushinteger(L, ATSPI_ROLE_COMBO_BOX);
356         lua_setglobal(L, "COMBO_BOX");
357         lua_pushinteger(L, ATSPI_ROLE_DATE_EDITOR);
358         lua_setglobal(L, "DATE_EDITOR");
359         lua_pushinteger(L, ATSPI_ROLE_DESKTOP_ICON);
360         lua_setglobal(L, "DESKTOP_ICON");
361         lua_pushinteger(L, ATSPI_ROLE_DESKTOP_FRAME);
362         lua_setglobal(L, "DESKTOP_FRAME");
363         lua_pushinteger(L, ATSPI_ROLE_DIAL);
364         lua_setglobal(L, "DIAL");
365         lua_pushinteger(L, ATSPI_ROLE_DIALOG);
366         lua_setglobal(L, "DIALOG");
367         lua_pushinteger(L, ATSPI_ROLE_DIRECTORY_PANE);
368         lua_setglobal(L, "DIRECTORY_PANE");
369         lua_pushinteger(L, ATSPI_ROLE_DRAWING_AREA);
370         lua_setglobal(L, "DRAWING_AREA");
371         lua_pushinteger(L, ATSPI_ROLE_FILE_CHOOSER);
372         lua_setglobal(L, "FILE_CHOOSER");
373         lua_pushinteger(L, ATSPI_ROLE_FILLER);
374         lua_setglobal(L, "FILLER");
375         lua_pushinteger(L, ATSPI_ROLE_FOCUS_TRAVERSABLE);
376         lua_setglobal(L, "FOCUS_TRAVERSABLE");
377         lua_pushinteger(L, ATSPI_ROLE_FONT_CHOOSER);
378         lua_setglobal(L, "FONT_CHOOSER");
379         lua_pushinteger(L, ATSPI_ROLE_FRAME);
380         lua_setglobal(L, "FRAME");
381         lua_pushinteger(L, ATSPI_ROLE_GLASS_PANE);
382         lua_setglobal(L, "GLASS_PANE");
383         lua_pushinteger(L, ATSPI_ROLE_HTML_CONTAINER);
384         lua_setglobal(L, "HTML_CONTAINER");
385         lua_pushinteger(L, ATSPI_ROLE_ICON);
386         lua_setglobal(L, "ICON");
387         lua_pushinteger(L, ATSPI_ROLE_IMAGE);
388         lua_setglobal(L, "IMAGE");
389         lua_pushinteger(L, ATSPI_ROLE_INTERNAL_FRAME);
390         lua_setglobal(L, "INTERNAL_FRAME");
391         lua_pushinteger(L, ATSPI_ROLE_LABEL);
392         lua_setglobal(L, "LABEL");
393         lua_pushinteger(L, ATSPI_ROLE_LAYERED_PANE);
394         lua_setglobal(L, "LAYERED_PANE");
395         lua_pushinteger(L, ATSPI_ROLE_LIST);
396         lua_setglobal(L, "LIST");
397         lua_pushinteger(L, ATSPI_ROLE_LIST_ITEM);
398         lua_setglobal(L, "LIST_ITEM");
399         lua_pushinteger(L, ATSPI_ROLE_MENU);
400         lua_setglobal(L, "MENU");
401         lua_pushinteger(L, ATSPI_ROLE_MENU_BAR);
402         lua_setglobal(L, "MENU_BAR");
403         lua_pushinteger(L, ATSPI_ROLE_MENU_ITEM);
404         lua_setglobal(L, "MENU_ITEM");
405         lua_pushinteger(L, ATSPI_ROLE_OPTION_PANE);
406         lua_setglobal(L, "OPTION_PANE");
407         lua_pushinteger(L, ATSPI_ROLE_PAGE_TAB);
408         lua_setglobal(L, "PAGE_TAB");
409         lua_pushinteger(L, ATSPI_ROLE_PAGE_TAB_LIST);
410         lua_setglobal(L, "PAGE_TAB_LIST");
411         lua_pushinteger(L, ATSPI_ROLE_PANEL);
412         lua_setglobal(L, "PANEL");
413         lua_pushinteger(L, ATSPI_ROLE_PASSWORD_TEXT);
414         lua_setglobal(L, "PASSWORD_TEXT");
415         lua_pushinteger(L, ATSPI_ROLE_POPUP_MENU);
416         lua_setglobal(L, "POPUP_MENU");
417         lua_pushinteger(L, ATSPI_ROLE_PROGRESS_BAR);
418         lua_setglobal(L, "PROGRESS_BAR");
419         lua_pushinteger(L, ATSPI_ROLE_PUSH_BUTTON);
420         lua_setglobal(L, "PUSH_BUTTON");
421         lua_pushinteger(L, ATSPI_ROLE_RADIO_BUTTON);
422         lua_setglobal(L, "RADIO_BUTTON");
423         lua_pushinteger(L, ATSPI_ROLE_RADIO_MENU_ITEM);
424         lua_setglobal(L, "RADIO_MENU_ITEM");
425         lua_pushinteger(L, ATSPI_ROLE_ROOT_PANE);
426         lua_setglobal(L, "ROOT_PANE");
427         lua_pushinteger(L, ATSPI_ROLE_ROW_HEADER);
428         lua_setglobal(L, "ROW_HEADER");
429         lua_pushinteger(L, ATSPI_ROLE_SCROLL_BAR);
430         lua_setglobal(L, "SCROLL_BAR");
431         lua_pushinteger(L, ATSPI_ROLE_SCROLL_PANE);
432         lua_setglobal(L, "SCROLL_PANE");
433         lua_pushinteger(L, ATSPI_ROLE_SEPARATOR);
434         lua_setglobal(L, "SEPARATOR");
435         lua_pushinteger(L, ATSPI_ROLE_SLIDER);
436         lua_setglobal(L, "SLIDER");
437         lua_pushinteger(L, ATSPI_ROLE_SPIN_BUTTON);
438         lua_setglobal(L, "SPIN_BUTTON");
439         lua_pushinteger(L, ATSPI_ROLE_SPLIT_PANE);
440         lua_setglobal(L, "SPLIT_PANE");
441         lua_pushinteger(L, ATSPI_ROLE_STATUS_BAR);
442         lua_setglobal(L, "STATUS_BAR");
443         lua_pushinteger(L, ATSPI_ROLE_TABLE);
444         lua_setglobal(L, "TABLE");
445         lua_pushinteger(L, ATSPI_ROLE_TABLE_CELL);
446         lua_setglobal(L, "TABLE_CELL");
447         lua_pushinteger(L, ATSPI_ROLE_TABLE_COLUMN_HEADER);
448         lua_setglobal(L, "TABLE_COLUMN_HEADER");
449         lua_pushinteger(L, ATSPI_ROLE_TABLE_ROW_HEADER);
450         lua_setglobal(L, "TABLE_ROW_HEADER");
451         lua_pushinteger(L, ATSPI_ROLE_TEAROFF_MENU_ITEM);
452         lua_setglobal(L, "TEAROFF_MENU_ITEM");
453         lua_pushinteger(L, ATSPI_ROLE_TERMINAL);
454         lua_setglobal(L, "TERMINAL");
455         lua_pushinteger(L, ATSPI_ROLE_TEXT);
456         lua_setglobal(L, "TEXT");
457         lua_pushinteger(L, ATSPI_ROLE_TOGGLE_BUTTON);
458         lua_setglobal(L, "TOGGLE_BUTTON");
459         lua_pushinteger(L, ATSPI_ROLE_TOOL_BAR);
460         lua_setglobal(L, "TOOL_BAR");
461         lua_pushinteger(L, ATSPI_ROLE_TOOL_TIP);
462         lua_setglobal(L, "TOOL_TIP");
463         lua_pushinteger(L, ATSPI_ROLE_TREE);
464         lua_setglobal(L, "TREE");
465         lua_pushinteger(L, ATSPI_ROLE_TREE_TABLE);
466         lua_setglobal(L, "TREE_TABLE");
467         lua_pushinteger(L, ATSPI_ROLE_UNKNOWN);
468         lua_setglobal(L, "UNKNOWN");
469         lua_pushinteger(L, ATSPI_ROLE_VIEWPORT);
470         lua_setglobal(L, "VIEWPORT");
471         lua_pushinteger(L, ATSPI_ROLE_WINDOW);
472         lua_setglobal(L, "WINDOW");
473         lua_pushinteger(L, ATSPI_ROLE_EXTENDED);
474         lua_setglobal(L, "EXTENDED");
475         lua_pushinteger(L, ATSPI_ROLE_HEADER);
476         lua_setglobal(L, "HEADER");
477         lua_pushinteger(L, ATSPI_ROLE_FOOTER);
478         lua_setglobal(L, "FOOTER");
479         lua_pushinteger(L, ATSPI_ROLE_PARAGRAPH);
480         lua_setglobal(L, "PARAGRAPH");
481         lua_pushinteger(L, ATSPI_ROLE_RULER);
482         lua_setglobal(L, "RULER");
483         lua_pushinteger(L, ATSPI_ROLE_APPLICATION);
484         lua_setglobal(L, "APPLICATION");
485         lua_pushinteger(L, ATSPI_ROLE_AUTOCOMPLETE);
486         lua_setglobal(L, "AUTOCOMPLETE");
487         lua_pushinteger(L, ATSPI_ROLE_EDITBAR);
488         lua_setglobal(L, "EDITBAR");
489         lua_pushinteger(L, ATSPI_ROLE_EMBEDDED);
490         lua_setglobal(L, "EMBEDDED");
491         lua_pushinteger(L, ATSPI_ROLE_ENTRY);
492         lua_setglobal(L, "ENTRY");
493         lua_pushinteger(L, ATSPI_ROLE_CHART);
494         lua_setglobal(L, "CHART");
495         lua_pushinteger(L, ATSPI_ROLE_CAPTION);
496         lua_setglobal(L, "CAPTION");
497         lua_pushinteger(L, ATSPI_ROLE_DOCUMENT_FRAME);
498         lua_setglobal(L, "DOCUMENT_FRAME");
499         lua_pushinteger(L, ATSPI_ROLE_HEADING);
500         lua_setglobal(L, "HEADING");
501         lua_pushinteger(L, ATSPI_ROLE_PAGE);
502         lua_setglobal(L, "PAGE");
503         lua_pushinteger(L, ATSPI_ROLE_SECTION);
504         lua_setglobal(L, "SECTION");
505         lua_pushinteger(L, ATSPI_ROLE_REDUNDANT_OBJECT);
506         lua_setglobal(L, "REDUNDANT_OBJECT");
507         lua_pushinteger(L, ATSPI_ROLE_FORM);
508         lua_setglobal(L, "FORM");
509         lua_pushinteger(L, ATSPI_ROLE_LINK);
510         lua_setglobal(L, "LINK");
511         lua_pushinteger(L, ATSPI_ROLE_INPUT_METHOD_WINDOW);
512         lua_setglobal(L, "INPUT_METHOD_WINDOW");
513         lua_pushinteger(L, ATSPI_ROLE_TABLE_ROW);
514         lua_setglobal(L, "TABLE_ROW");
515         lua_pushinteger(L, ATSPI_ROLE_TREE_ITEM);
516         lua_setglobal(L, "TREE_ITEM");
517         lua_pushinteger(L, ATSPI_ROLE_DOCUMENT_SPREADSHEET);
518         lua_setglobal(L, "DOCUMENT_SPREADSHEET");
519         lua_pushinteger(L, ATSPI_ROLE_DOCUMENT_PRESENTATION);
520         lua_setglobal(L, "DOCUMENT_PRESENTATION");
521         lua_pushinteger(L, ATSPI_ROLE_DOCUMENT_TEXT);
522         lua_setglobal(L, "DOCUMENT_TEXT");
523         lua_pushinteger(L, ATSPI_ROLE_DOCUMENT_WEB);
524         lua_setglobal(L, "DOCUMENT_WEB");
525         lua_pushinteger(L, ATSPI_ROLE_DOCUMENT_EMAIL);
526         lua_setglobal(L, "DOCUMENT_EMAIL");
527         lua_pushinteger(L, ATSPI_ROLE_COMMENT);
528         lua_setglobal(L, "COMMENT");
529         lua_pushinteger(L, ATSPI_ROLE_LIST_BOX);
530         lua_setglobal(L, "LIST_BOX");
531         lua_pushinteger(L, ATSPI_ROLE_GROUPING);
532         lua_setglobal(L, "GROUPING");
533         lua_pushinteger(L, ATSPI_ROLE_IMAGE_MAP);
534         lua_setglobal(L, "IMAGE_MAP");
535         lua_pushinteger(L, ATSPI_ROLE_NOTIFICATION);
536         lua_setglobal(L, "NOTIFICATION");
537         lua_pushinteger(L, ATSPI_ROLE_INFO_BAR);
538         lua_setglobal(L, "INFO_BAR");
539         lua_pushinteger(L, ATSPI_ROLE_LEVEL_BAR);
540         lua_setglobal(L, "LEVEL_BAR");
541         lua_pushinteger(L, ATSPI_ROLE_TITLE_BAR);
542         lua_setglobal(L, "TITLE_BAR");
543         lua_pushinteger(L, ATSPI_ROLE_BLOCK_QUOTE);
544         lua_setglobal(L, "BLOCK_QUOTE");
545         lua_pushinteger(L, ATSPI_ROLE_AUDIO);
546         lua_setglobal(L, "AUDIO");
547         lua_pushinteger(L, ATSPI_ROLE_VIDEO);
548         lua_setglobal(L, "VIDEO");
549         lua_pushinteger(L, ATSPI_ROLE_DEFINITION);
550         lua_setglobal(L, "DEFINITION");
551         lua_pushinteger(L, ATSPI_ROLE_ARTICLE);
552         lua_setglobal(L, "ARTICLE");
553         lua_pushinteger(L, ATSPI_ROLE_LANDMARK);
554         lua_setglobal(L, "LANDMARK");
555         lua_pushinteger(L, ATSPI_ROLE_LOG);
556         lua_setglobal(L, "LOG");
557         lua_pushinteger(L, ATSPI_ROLE_MARQUEE);
558         lua_setglobal(L, "MARQUEE");
559         lua_pushinteger(L, ATSPI_ROLE_MATH);
560         lua_setglobal(L, "MATH");
561         lua_pushinteger(L, ATSPI_ROLE_RATING);
562         lua_setglobal(L, "RATING");
563         lua_pushinteger(L, ATSPI_ROLE_TIMER);
564         lua_setglobal(L, "TIMER");
565         lua_pushinteger(L, ATSPI_ROLE_STATIC);
566         lua_setglobal(L, "STATIC");
567         lua_pushinteger(L, ATSPI_ROLE_MATH_FRACTION);
568         lua_setglobal(L, "MATH_FRACTION");
569         lua_pushinteger(L, ATSPI_ROLE_MATH_ROOT);
570         lua_setglobal(L, "MATH_ROOT");
571         lua_pushinteger(L, ATSPI_ROLE_SUBSCRIPT);
572         lua_setglobal(L, "SUBSCRIPT");
573         lua_pushinteger(L, ATSPI_ROLE_SUPERSCRIPT);
574         lua_setglobal(L, "SUPERSCRIPT");
575         lua_pushinteger(L, ATSPI_ROLE_LAST_DEFINED);
576         lua_setglobal(L, "LAST_DEFINED");
577
578         // relations enums
579         lua_pushinteger(L, ATSPI_RELATION_NULL);
580         lua_setglobal(L, "RELATION_NULL");
581         lua_pushinteger(L, ATSPI_RELATION_LABEL_FOR);
582         lua_setglobal(L, "RELATION_LABEL_FOR");
583         lua_pushinteger(L, ATSPI_RELATION_LABELLED_BY);
584         lua_setglobal(L, "RELATION_LABELLED_BY");
585         lua_pushinteger(L, ATSPI_RELATION_CONTROLLER_FOR);
586         lua_setglobal(L, "RELATION_CONTROLLER_FOR");
587         lua_pushinteger(L, ATSPI_RELATION_CONTROLLED_BY);
588         lua_setglobal(L, "RELATION_CONTROLLED_BY");
589         lua_pushinteger(L, ATSPI_RELATION_MEMBER_OF);
590         lua_setglobal(L, "RELATION_MEMBER_OF");
591         lua_pushinteger(L, ATSPI_RELATION_TOOLTIP_FOR);
592         lua_setglobal(L, "RELATION_TOOLTIP_FOR");
593         lua_pushinteger(L, ATSPI_RELATION_NODE_CHILD_OF);
594         lua_setglobal(L, "RELATION_NODE_CHILD_OF");
595         lua_pushinteger(L, ATSPI_RELATION_NODE_PARENT_OF);
596         lua_setglobal(L, "RELATION_NODE_PARENT_OF");
597         lua_pushinteger(L, ATSPI_RELATION_EXTENDED);
598         lua_setglobal(L, "RELATION_EXTENDED");
599         lua_pushinteger(L, ATSPI_RELATION_FLOWS_TO);
600         lua_setglobal(L, "RELATION_FLOWS_TO");
601         lua_pushinteger(L, ATSPI_RELATION_FLOWS_FROM);
602         lua_setglobal(L, "RELATION_FLOWS_FROM");
603         lua_pushinteger(L, ATSPI_RELATION_SUBWINDOW_OF);
604         lua_setglobal(L, "RELATION_SUBWINDOW_OF");
605         lua_pushinteger(L, ATSPI_RELATION_EMBEDS);
606         lua_setglobal(L, "RELATION_EMBEDS");
607         lua_pushinteger(L, ATSPI_RELATION_EMBEDDED_BY);
608         lua_setglobal(L, "RELATION_EMBEDDED_BY");
609         lua_pushinteger(L, ATSPI_RELATION_POPUP_FOR);
610         lua_setglobal(L, "RELATION_POPUP_FOR");
611         lua_pushinteger(L, ATSPI_RELATION_PARENT_WINDOW_OF);
612         lua_setglobal(L, "RELATION_PARENT_WINDOW_OF");
613         lua_pushinteger(L, ATSPI_RELATION_DESCRIPTION_FOR);
614         lua_setglobal(L, "RELATION_DESCRIPTION_FOR");
615         lua_pushinteger(L, ATSPI_RELATION_DESCRIBED_BY);
616         lua_setglobal(L, "RELATION_DESCRIBED_BY");
617         lua_pushinteger(L, ATSPI_RELATION_LAST_DEFINED);
618         lua_setglobal(L, "RELATION_LAST_DEFINED");
619
620         // state enums
621         lua_pushinteger(L, ATSPI_STATE_INVALID);
622         lua_setglobal(L, "INVALID");
623         lua_pushinteger(L, ATSPI_STATE_ACTIVE);
624         lua_setglobal(L, "ACTIVE");
625         lua_pushinteger(L, ATSPI_STATE_ARMED);
626         lua_setglobal(L, "ARMED");
627         lua_pushinteger(L, ATSPI_STATE_BUSY);
628         lua_setglobal(L, "BUSY");
629         lua_pushinteger(L, ATSPI_STATE_CHECKED);
630         lua_setglobal(L, "CHECKED");
631         lua_pushinteger(L, ATSPI_STATE_COLLAPSED);
632         lua_setglobal(L, "COLLAPSED");
633         lua_pushinteger(L, ATSPI_STATE_DEFUNCT);
634         lua_setglobal(L, "DEFUNCT");
635         lua_pushinteger(L, ATSPI_STATE_EDITABLE);
636         lua_setglobal(L, "EDITABLE");
637         lua_pushinteger(L, ATSPI_STATE_ENABLED);
638         lua_setglobal(L, "ENABLED");
639         lua_pushinteger(L, ATSPI_STATE_EXPANDABLE);
640         lua_setglobal(L, "EXPANDABLE");
641         lua_pushinteger(L, ATSPI_STATE_EXPANDED);
642         lua_setglobal(L, "EXPANDED");
643         lua_pushinteger(L, ATSPI_STATE_FOCUSABLE);
644         lua_setglobal(L, "FOCUSABLE");
645         lua_pushinteger(L, ATSPI_STATE_FOCUSED);
646         lua_setglobal(L, "FOCUSED");
647         lua_pushinteger(L, ATSPI_STATE_HAS_TOOLTIP);
648         lua_setglobal(L, "HAS_TOOLTIP");
649         lua_pushinteger(L, ATSPI_STATE_HORIZONTAL);
650         lua_setglobal(L, "HORIZONTAL");
651         lua_pushinteger(L, ATSPI_STATE_ICONIFIED);
652         lua_setglobal(L, "ICONIFIED");
653         lua_pushinteger(L, ATSPI_STATE_MODAL);
654         lua_setglobal(L, "MODAL");
655         lua_pushinteger(L, ATSPI_STATE_MULTI_LINE);
656         lua_setglobal(L, "MULTI_LINE");
657         lua_pushinteger(L, ATSPI_STATE_MULTISELECTABLE);
658         lua_setglobal(L, "MULTISELECTABLE");
659         lua_pushinteger(L, ATSPI_STATE_OPAQUE);
660         lua_setglobal(L, "OPAQUE");
661         lua_pushinteger(L, ATSPI_STATE_PRESSED);
662         lua_setglobal(L, "PRESSED");
663         lua_pushinteger(L, ATSPI_STATE_RESIZABLE);
664         lua_setglobal(L, "RESIZABLE");
665         lua_pushinteger(L, ATSPI_STATE_SELECTABLE);
666         lua_setglobal(L, "SELECTABLE");
667         lua_pushinteger(L, ATSPI_STATE_SELECTED);
668         lua_setglobal(L, "SELECTED");
669         lua_pushinteger(L, ATSPI_STATE_SENSITIVE);
670         lua_setglobal(L, "SENSITIVE");
671         lua_pushinteger(L, ATSPI_STATE_SHOWING);
672         lua_setglobal(L, "SHOWING");
673         lua_pushinteger(L, ATSPI_STATE_SINGLE_LINE);
674         lua_setglobal(L, "SINGLE_LINE");
675         lua_pushinteger(L, ATSPI_STATE_STALE);
676         lua_setglobal(L, "STALE");
677         lua_pushinteger(L, ATSPI_STATE_TRANSIENT);
678         lua_setglobal(L, "TRANSIENT");
679         lua_pushinteger(L, ATSPI_STATE_VERTICAL);
680         lua_setglobal(L, "VERTICAL");
681         lua_pushinteger(L, ATSPI_STATE_VISIBLE);
682         lua_setglobal(L, "VISIBLE");
683         lua_pushinteger(L, ATSPI_STATE_MANAGES_DESCENDANTS);
684         lua_setglobal(L, "MANAGES_DESCENDANTS");
685         lua_pushinteger(L, ATSPI_STATE_INDETERMINATE);
686         lua_setglobal(L, "INDETERMINATE");
687         lua_pushinteger(L, ATSPI_STATE_REQUIRED);
688         lua_setglobal(L, "REQUIRED");
689         lua_pushinteger(L, ATSPI_STATE_TRUNCATED);
690         lua_setglobal(L, "TRUNCATED");
691         lua_pushinteger(L, ATSPI_STATE_ANIMATED);
692         lua_setglobal(L, "ANIMATED");
693         lua_pushinteger(L, ATSPI_STATE_INVALID_ENTRY);
694         lua_setglobal(L, "INVALID_ENTRY");
695         lua_pushinteger(L, ATSPI_STATE_SUPPORTS_AUTOCOMPLETION);
696         lua_setglobal(L, "SUPPORTS_AUTOCOMPLETION");
697         lua_pushinteger(L, ATSPI_STATE_SELECTABLE_TEXT);
698         lua_setglobal(L, "SELECTABLE_TEXT");
699         lua_pushinteger(L, ATSPI_STATE_IS_DEFAULT);
700         lua_setglobal(L, "IS_DEFAULT");
701         lua_pushinteger(L, ATSPI_STATE_VISITED);
702         lua_setglobal(L, "VISITED");
703         lua_pushinteger(L, ATSPI_STATE_HIGHLIGHTED);
704         lua_setglobal(L, "HIGHLIGHTED");
705         lua_pushinteger(L, ATSPI_STATE_LAST_DEFINED);
706         lua_setglobal(L, "LAST_DEFINED");
707 }
708
709 static void _register_class(lua_State *L, const char *class_name, const luaL_Reg *funcs)
710 {
711         lua_newtable(L);
712         int methodtable = lua_gettop(L);
713         luaL_newmetatable(L, class_name);
714         int metatable = lua_gettop(L);
715
716         lua_pushliteral(L, "__metatable");
717         lua_pushvalue(L, methodtable);
718         lua_settable(L, metatable);
719
720         lua_pushliteral(L, "__index");
721         lua_pushvalue(L, methodtable);
722         lua_settable(L, metatable);
723
724         luaI_openlib(L, 0, _meta_methods, 0);
725
726         lua_pop(L, 1);
727
728         luaI_openlib(L, 0, funcs, 0);
729         lua_pop(L, 1);
730 }
731
732 static int _extensions_register(lua_State *L)
733 {
734         _register_class(L, ACCESSIBLE_CLASS_NAME, _accessible_methods);
735         _register_class(L, VALUE_CLASS_NAME, _value_methods);
736         _register_class(L, SELECTION_CLASS_NAME, _selection_methods);
737
738         _register_role_enums(L);
739
740         lua_register(L, "desktop", l_get_root);
741         lua_register(L, "T", l_get_translation);
742
743         return 0;
744 }
745
746 int lua_engine_init(const char *script)
747 {
748         L = luaL_newstate();
749
750         luaL_openlibs(L);
751
752         DEBUG("Initializing lua engine with script file: %s", script);
753
754         if (_extensions_register(L))
755         {
756                 ERROR("Failed to load screen-reader lua extensions");
757                 lua_close(L);
758                 return -1;
759         }
760         if (luaL_loadfile(L, script))
761         {
762                 ERROR("Script loading failed: %s\n", lua_tostring(L, -1));
763                 lua_close(L);
764                 return -1;
765         }
766         if (lua_pcall(L, 0, 0, 0))
767         {
768                 ERROR("Failed to init lua script: %s", lua_tostring(L, -1));
769                 lua_close(L);
770                 return -1;
771         }
772         DEBUG("Lua engine successfully inited.");
773         return 0;
774 }
775
776 void lua_engine_shutdown(void)
777 {
778         lua_close(L);
779 }
780
781 char *lua_engine_describe_object(AtspiAccessible *obj)
782 {
783         const char *ret = NULL;
784
785         // get 'describeObject' function and push arguments on stack
786         lua_getglobal(L, "describeObject");
787
788         _push_class_obj(L, obj, ACCESSIBLE_CLASS_NAME);
789
790         // launch function
791         if (lua_pcall(L, 1, 1, 0))
792         {
793                 ERROR("Failed to run function 'describeObject': %s", lua_tostring(L, -1));
794                 goto end;
795         }
796         // get result from lua stack
797         if (!lua_isstring(L, -1))
798         {
799                 ERROR("Function 'describeObject' do not returned string value.");
800                 goto end;
801         }
802         ret = lua_tostring(L, -1);
803
804 end:
805         // unref all AtspiAccessible references
806         lua_gc(L, LUA_GCCOLLECT, 1);
807         lua_pop(L, 1);
808         return ret ? strdup(ret) : NULL;
809 }