diff options
Diffstat (limited to '')
-rw-r--r-- | ClientHamr/GuiLua/GuiLua.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/ClientHamr/GuiLua/GuiLua.c b/ClientHamr/GuiLua/GuiLua.c index d70aabc..03a7bd5 100644 --- a/ClientHamr/GuiLua/GuiLua.c +++ b/ClientHamr/GuiLua/GuiLua.c | |||
@@ -120,3 +120,344 @@ that has hard coded mappings between some basic "label", "button", etc. | |||
120 | and ordinary elementary widgets. Proper introspection can come later. | 120 | and ordinary elementary widgets. Proper introspection can come later. |
121 | 121 | ||
122 | */ | 122 | */ |
123 | |||
124 | |||
125 | |||
126 | #include <Eet.h> | ||
127 | #include <Ecore.h> | ||
128 | #include <Ecore_Evas.h> | ||
129 | #include <Edje.h> | ||
130 | #include <stdio.h> | ||
131 | #include <ctype.h> | ||
132 | |||
133 | #include <lua.h> | ||
134 | #include <luajit.h> | ||
135 | #include <lualib.h> | ||
136 | #include <lauxlib.h> | ||
137 | |||
138 | typedef struct _globals globals; | ||
139 | |||
140 | |||
141 | #define WIDTH (300) | ||
142 | #define HEIGHT (300) | ||
143 | |||
144 | #define PC(...) EINA_LOG_DOM_CRIT(ourGlobals->logDom, __VA_ARGS__) | ||
145 | #define PE(...) EINA_LOG_DOM_ERR(ourGlobals->logDom, __VA_ARGS__) | ||
146 | #define PW(...) EINA_LOG_DOM_WARN(ourGlobals->logDom, __VA_ARGS__) | ||
147 | #define PD(...) EINA_LOG_DOM_DBG(ourGlobals->logDom, __VA_ARGS__) | ||
148 | #define PI(...) EINA_LOG_DOM_INFO(ourGlobals->logDom, __VA_ARGS__) | ||
149 | |||
150 | #define PCm(...) EINA_LOG_DOM_CRIT(ourGlobals.logDom, __VA_ARGS__) | ||
151 | #define PEm(...) EINA_LOG_DOM_ERR(ourGlobals.logDom, __VA_ARGS__) | ||
152 | #define PWm(...) EINA_LOG_DOM_WARN(ourGlobals.logDom, __VA_ARGS__) | ||
153 | #define PDm(...) EINA_LOG_DOM_DBG(ourGlobals.logDom, __VA_ARGS__) | ||
154 | #define PIm(...) EINA_LOG_DOM_INFO(ourGlobals.logDom, __VA_ARGS__) | ||
155 | |||
156 | #define D() PD("DEBUG") | ||
157 | |||
158 | // "01:03:52 01-01-1973\n\0" | ||
159 | #define DATE_TIME_LEN 21 | ||
160 | |||
161 | |||
162 | #ifndef FALSE | ||
163 | // NEVER change this | ||
164 | typedef enum | ||
165 | { | ||
166 | FALSE = 0, | ||
167 | TRUE = 1 | ||
168 | } boolean; | ||
169 | #endif | ||
170 | |||
171 | struct _globals | ||
172 | { | ||
173 | Ecore_Evas *ee; // Our window. | ||
174 | Evas *canvas; // The canvas for drawing directly onto. | ||
175 | Evas_Object *bg; // Our background edje. | ||
176 | lua_State *L; // Our Lua state. | ||
177 | int logDom; | ||
178 | }; | ||
179 | |||
180 | |||
181 | |||
182 | static const char *ourName = "widget"; | ||
183 | int skang, _M; | ||
184 | |||
185 | static int wfunc (lua_State *L) | ||
186 | { | ||
187 | double arg1 = luaL_checknumber(L, 1); | ||
188 | const char *arg2 = luaL_checkstring(L, 2); | ||
189 | |||
190 | printf("Inside %s.wfunc(%f, %s)\n", ourName, arg1, arg2); | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | |||
195 | |||
196 | char *getDateTime(struct tm **nowOut, char *dateOut, time_t *tiemOut); | ||
197 | |||
198 | |||
199 | |||
200 | # define DATE_TIME_LEN 21 | ||
201 | |||
202 | char dateTime[DATE_TIME_LEN]; | ||
203 | |||
204 | static | ||
205 | void _ggg_log_print_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc, int line, const char *fmt, void *data, va_list args) | ||
206 | { | ||
207 | FILE *f = data; | ||
208 | char dt[DATE_TIME_LEN + 1]; | ||
209 | char fileTab[256], funcTab[256]; | ||
210 | |||
211 | getDateTime(NULL, dt, NULL); | ||
212 | dt[19] = '\0'; | ||
213 | if (12 > strlen(file)) | ||
214 | snprintf(fileTab, sizeof(fileTab), "%s\t\t", file); | ||
215 | else | ||
216 | snprintf(fileTab, sizeof(fileTab), "%s\t", file); | ||
217 | snprintf(funcTab, sizeof(funcTab), "\t%s", fnc); | ||
218 | fprintf(f, "%s ", dt); | ||
219 | if (f == stderr) | ||
220 | eina_log_print_cb_stderr(d, level, fileTab, funcTab, line, fmt, data, args); | ||
221 | else if (f == stdout) | ||
222 | eina_log_print_cb_stdout(d, level, fileTab, funcTab, line, fmt, data, args); | ||
223 | fflush(f); | ||
224 | } | ||
225 | |||
226 | void loggingStartup(globals *ourGlobals) | ||
227 | { | ||
228 | ourGlobals->logDom = eina_log_domain_register("GuiLua", NULL); | ||
229 | if (ourGlobals->logDom < 0) | ||
230 | { | ||
231 | EINA_LOG_CRIT("could not register log domain 'GuiLua'"); | ||
232 | } | ||
233 | // TODO - should unregister this later. | ||
234 | eina_log_level_set(EINA_LOG_LEVEL_DBG); | ||
235 | eina_log_domain_level_set("GuiLua", EINA_LOG_LEVEL_DBG); | ||
236 | eina_log_print_cb_set(_ggg_log_print_cb, stderr); | ||
237 | |||
238 | // Shut up the excess debugging shit from EFL. | ||
239 | eina_log_domain_level_set("eo", EINA_LOG_LEVEL_WARN); | ||
240 | eina_log_domain_level_set("eet", EINA_LOG_LEVEL_WARN); | ||
241 | eina_log_domain_level_set("ecore", EINA_LOG_LEVEL_WARN); | ||
242 | eina_log_domain_level_set("ecore_audio", EINA_LOG_LEVEL_WARN); | ||
243 | eina_log_domain_level_set("ecore_evas", EINA_LOG_LEVEL_WARN); | ||
244 | eina_log_domain_level_set("ecore_input_evas", EINA_LOG_LEVEL_WARN); | ||
245 | eina_log_domain_level_set("ecore_system_upower", EINA_LOG_LEVEL_WARN); | ||
246 | eina_log_domain_level_set("ecore_x", EINA_LOG_LEVEL_WARN); | ||
247 | eina_log_domain_level_set("evas_main", EINA_LOG_LEVEL_WARN); | ||
248 | eina_log_domain_level_set("eldbus", EINA_LOG_LEVEL_WARN); | ||
249 | } | ||
250 | |||
251 | char *getDateTime(struct tm **nowOut, char *dateOut, time_t *timeOut) | ||
252 | { | ||
253 | struct tm *newTime; | ||
254 | time_t szClock; | ||
255 | char *date = dateTime; | ||
256 | |||
257 | // Get time in seconds | ||
258 | time(&szClock); | ||
259 | // Convert time to struct tm form | ||
260 | newTime = localtime(&szClock); | ||
261 | |||
262 | if (nowOut) | ||
263 | *nowOut = newTime; | ||
264 | if (dateOut) | ||
265 | date = dateOut; | ||
266 | if (timeOut) | ||
267 | *timeOut = szClock; | ||
268 | |||
269 | // format | ||
270 | strftime(date, DATE_TIME_LEN, "%d/%m/%Y %H:%M:%S\r", newTime); | ||
271 | return (dateTime); | ||
272 | } | ||
273 | |||
274 | |||
275 | |||
276 | static void | ||
277 | _on_delete(Ecore_Evas *ee /*__UNUSED__*/) | ||
278 | { | ||
279 | ecore_main_loop_quit(); | ||
280 | } | ||
281 | |||
282 | |||
283 | /* local widget = require 'widget' | ||
284 | |||
285 | Lua's require() function will strip any stuff from the front of the name | ||
286 | separated by a hyphen, so 'ClientHamr-GuiLua-test_c' -> 'test_c'. Then | ||
287 | it will search through a path, and eventually find this test_c.so (or | ||
288 | test_c.dll or whatever), then call luaopen_test_c(), which should return | ||
289 | a table. The argument (only thing on the stack) for this function will | ||
290 | be 'test_c'. | ||
291 | |||
292 | Normally luaL_register() creates a table of functions, that is the table | ||
293 | returned, but we want to do something different with skang. | ||
294 | */ | ||
295 | int luaopen_widget(lua_State *L) | ||
296 | { | ||
297 | lua_Number i; | ||
298 | |||
299 | // In theory, the only thing on the stack now is 'widget' from the require() call. | ||
300 | |||
301 | // pseudo-indices, special tables that can be accessed like the stack - | ||
302 | // LUA_GLOBALSINDEX - thread environment, where globals are | ||
303 | // LUA_ENVIRONINDEX - C function environment, in this case luaopen_test_c() is the C function | ||
304 | // LUA_REGISTRYINDEX - C registry, global, for unique keys use the module name as a string, or a lightuserdata address to a C object in our module. | ||
305 | // lua_upvalueindex(n) - C function upvalues | ||
306 | |||
307 | // The only locals we care about are skang and _M. | ||
308 | // All modules go into package.loaded[name] as well. | ||
309 | // skang is essentially a global anyway. | ||
310 | // _M we pass back as the result, and our functions get added to it by skang.thingasm() | ||
311 | // Not entirely true, _M is a proxy table, getmetatable(_M).__values[cfunc] would be our function. | ||
312 | |||
313 | // local skang = require 'skang' | ||
314 | lua_getglobal(L, "require"); | ||
315 | lua_pushstring(L, "skang"); | ||
316 | lua_call(L, 1, 1); | ||
317 | skang = lua_gettop(L); | ||
318 | |||
319 | // local _M = skang.moduleBegin('widget', nil, 'Copyright 2014 David Seikel', '0.1', '2014-04-08 00:42:00', nil, false) | ||
320 | lua_getfield(L, skang, "moduleBegin"); | ||
321 | lua_pushstring(L, ourName); | ||
322 | lua_pushnil(L); // Author comes from copyright. | ||
323 | lua_pushstring(L, "Copyright 2014 David Seikel"); | ||
324 | lua_pushstring(L, "0.1"); | ||
325 | lua_pushstring(L, "2014-04-08 00:42:00"); | ||
326 | lua_pushnil(L); // No skin. | ||
327 | lua_pushboolean(L, 0); // We are not a Lua module. | ||
328 | lua_call(L, 7, 1); // call 'skang.moduleBegin' with 7 arguments and 1 result. | ||
329 | |||
330 | _M = lua_gettop(L); | ||
331 | // Save this module in the C registry. | ||
332 | lua_setfield(L, LUA_REGISTRYINDEX, ourName); | ||
333 | |||
334 | // This uses function{} style. | ||
335 | // skang.thingasm{_M, 'wfooble,c', 'wfooble help text', 1, widget=\"'edit', 'The wfooble:', 1, 1, 10, 50\", required=true} | ||
336 | lua_getfield(L, skang, "thingasm"); | ||
337 | i = 1; | ||
338 | lua_newtable(L); | ||
339 | lua_pushnumber(L, i++); | ||
340 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. | ||
341 | lua_settable(L, -3); | ||
342 | |||
343 | lua_pushnumber(L, i++); | ||
344 | lua_pushstring(L, "wfooble,w"); | ||
345 | lua_settable(L, -3); | ||
346 | |||
347 | lua_pushnumber(L, i++); | ||
348 | lua_pushstring(L, "wfooble help text"); | ||
349 | lua_settable(L, -3); | ||
350 | |||
351 | lua_pushnumber(L, i++); | ||
352 | lua_pushnumber(L, 1); | ||
353 | lua_settable(L, -3); | ||
354 | |||
355 | lua_pushstring(L, "'edit', 'The wfooble:', 1, 1, 10, 50"); | ||
356 | lua_setfield(L, -2, "widget"); | ||
357 | lua_pushboolean(L, 1); // Is required. | ||
358 | lua_setfield(L, -2, "required"); | ||
359 | lua_call(L, 1, 0); | ||
360 | |||
361 | // skang.thing(_M, 'wbar', 'Help text', 'Default') | ||
362 | lua_getfield(L, skang, "thingasm"); | ||
363 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. | ||
364 | lua_pushstring(L, "wbar"); | ||
365 | lua_pushstring(L, "Help text"); | ||
366 | lua_pushstring(L, "Default"); | ||
367 | lua_call(L, 4, 0); | ||
368 | |||
369 | // skang.thingasm(_M, 'cfoo') | ||
370 | lua_getfield(L, skang, "thingasm"); | ||
371 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. | ||
372 | lua_pushstring(L, "wfoo"); | ||
373 | lua_call(L, 2, 0); | ||
374 | |||
375 | // skang.thingasm(_M, 'cfunc', 'cfunc does nothing really', cfunc, 'number,string') | ||
376 | lua_getfield(L, skang, "thingasm"); | ||
377 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment. | ||
378 | lua_pushstring(L, "wfunc"); | ||
379 | lua_pushstring(L, "wfunc does nothing really"); | ||
380 | lua_pushcfunction(L, wfunc); | ||
381 | lua_pushstring(L, "number,string"); | ||
382 | lua_call(L, 5, 0); | ||
383 | |||
384 | // skang.moduleEnd(_M) | ||
385 | lua_getfield(L, skang, "moduleEnd"); | ||
386 | lua_getfield(L, LUA_REGISTRYINDEX, ourName); | ||
387 | lua_call(L, 1, 1); | ||
388 | |||
389 | return 1; | ||
390 | } | ||
391 | |||
392 | |||
393 | int main(int argc, char **argv) | ||
394 | { | ||
395 | globals ourGlobals; | ||
396 | int result = EXIT_FAILURE; | ||
397 | |||
398 | memset(&ourGlobals, 0, sizeof(globals)); | ||
399 | |||
400 | if (eina_init()) | ||
401 | { | ||
402 | loggingStartup(&ourGlobals); | ||
403 | |||
404 | PIm("GuiLua running as an application.\n"); | ||
405 | |||
406 | if (ecore_evas_init()) | ||
407 | { | ||
408 | if (edje_init()) | ||
409 | { | ||
410 | /* this will give you a window with an Evas canvas under the first engine available */ | ||
411 | ourGlobals.ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL); | ||
412 | if (!ourGlobals.ee) | ||
413 | { | ||
414 | PEm("You got to have at least one evas engine built and linked up to ecore-evas for this example to run properly."); | ||
415 | edje_shutdown(); | ||
416 | ecore_evas_shutdown(); | ||
417 | return -1; | ||
418 | } | ||
419 | ourGlobals.canvas = ecore_evas_get(ourGlobals.ee); | ||
420 | ecore_evas_title_set(ourGlobals.ee, "GuiLua test harness"); | ||
421 | ecore_evas_show(ourGlobals.ee); | ||
422 | |||
423 | ourGlobals.bg = evas_object_rectangle_add(ourGlobals.canvas); | ||
424 | evas_object_color_set(ourGlobals.bg, 255, 255, 255, 255); /* white bg */ | ||
425 | evas_object_move(ourGlobals.bg, 0, 0); /* at canvas' origin */ | ||
426 | evas_object_size_hint_weight_set(ourGlobals.bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | ||
427 | evas_object_resize(ourGlobals.bg, WIDTH, HEIGHT); /* covers full canvas */ | ||
428 | evas_object_show(ourGlobals.bg); | ||
429 | ecore_evas_object_associate(ourGlobals.ee, ourGlobals.bg, ECORE_EVAS_OBJECT_ASSOCIATE_BASE); | ||
430 | evas_object_focus_set(ourGlobals.bg, EINA_TRUE); | ||
431 | |||
432 | // Setup our callbacks. | ||
433 | ecore_evas_callback_delete_request_set(ourGlobals.ee, _on_delete); | ||
434 | |||
435 | ourGlobals.L = luaL_newstate(); | ||
436 | if (ourGlobals.L) | ||
437 | { | ||
438 | luaL_openlibs(ourGlobals.L); | ||
439 | luaopen_widget(ourGlobals.L); | ||
440 | |||
441 | ecore_main_loop_begin(); | ||
442 | |||
443 | lua_close(ourGlobals.L); | ||
444 | ecore_evas_free(ourGlobals.ee); | ||
445 | } | ||
446 | else | ||
447 | PCm("Failed to start Lua!"); | ||
448 | |||
449 | edje_shutdown(); | ||
450 | } | ||
451 | else | ||
452 | PCm("Failed to init edje!"); | ||
453 | |||
454 | ecore_evas_shutdown(); | ||
455 | } | ||
456 | else | ||
457 | PCm("Failed to init ecore_evas!"); | ||
458 | } | ||
459 | else | ||
460 | fprintf(stderr, "Failed to init eina!"); | ||
461 | |||
462 | return result; | ||
463 | } | ||