fix red.
[kugel-rb/myfork.git] / apps / plugins / lua / rocklib.c
blobc6b399c8a5b1884f13353df88bd88d69b0c6bfdb
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 Dan Everton (safetydan)
11 * Copyright (C) 2009 Maurus Cuelenaere
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 #define lrocklib_c
24 #define LUA_LIB
26 #include "lua.h"
28 #include "lauxlib.h"
29 #include "rocklib.h"
32 * http://www.lua.org/manual/5.1/manual.html#lua_CFunction
34 * In order to communicate properly with Lua, a C function must use the following protocol,
35 * which defines the way parameters and results are passed: a C function receives its arguments
36 * from Lua in its stack in direct order (the first argument is pushed first). To return values to Lua,
37 * a C function just pushes them onto the stack, in direct order (the first result is pushed first),
38 * and returns the number of results. Any other value in the stack below the results will be properly
39 * discarded by Lua. Like a Lua function, a C function called by Lua can also return many results.
44 * -----------------------------
46 * Rockbox Lua image wrapper
48 * -----------------------------
51 #define ROCKLUA_IMAGE "rb.image"
52 struct rocklua_image
54 int width;
55 int height;
56 fb_data *data;
57 fb_data dummy[1][1];
60 static void rli_wrap(lua_State *L, fb_data *src, int width, int height)
62 struct rocklua_image *a = (struct rocklua_image *)lua_newuserdata(L, sizeof(struct rocklua_image));
64 luaL_getmetatable(L, ROCKLUA_IMAGE);
65 lua_setmetatable(L, -2);
67 a->width = width;
68 a->height = height;
69 a->data = src;
72 static fb_data* rli_alloc(lua_State *L, int width, int height)
74 size_t nbytes = sizeof(struct rocklua_image) + ((width*height) - 1) * sizeof(fb_data);
75 struct rocklua_image *a = (struct rocklua_image *)lua_newuserdata(L, nbytes);
77 luaL_getmetatable(L, ROCKLUA_IMAGE);
78 lua_setmetatable(L, -2);
80 a->width = width;
81 a->height = height;
82 a->data = &a->dummy[0][0];
84 return a->data;
87 static int rli_new(lua_State *L)
89 int width = luaL_checkint(L, 1);
90 int height = luaL_checkint(L, 2);
92 rli_alloc(L, width, height);
94 return 1;
97 static struct rocklua_image* rli_checktype(lua_State *L, int arg)
99 void *ud = luaL_checkudata(L, arg, ROCKLUA_IMAGE);
100 luaL_argcheck(L, ud != NULL, arg, "'" ROCKLUA_IMAGE "' expected");
101 return (struct rocklua_image*) ud;
104 static int rli_width(lua_State *L)
106 struct rocklua_image *a = rli_checktype(L, 1);
107 lua_pushnumber(L, a->width);
108 return 1;
111 static int rli_height(lua_State *L)
113 struct rocklua_image *a = rli_checktype(L, 1);
114 lua_pushnumber(L, a->height);
115 return 1;
118 static fb_data* rli_element(lua_State *L)
120 struct rocklua_image *a = rli_checktype(L, 1);
121 int x = luaL_checkint(L, 2);
122 int y = luaL_checkint(L, 3);
124 luaL_argcheck(L, 1 <= x && x <= a->width, 2,
125 "index out of range");
126 luaL_argcheck(L, 1 <= y && y <= a->height, 3,
127 "index out of range");
129 /* return element address */
130 return &a->data[a->width * (y - 1) + (x - 1)];
133 static int rli_set(lua_State *L)
135 fb_data newvalue = (fb_data) luaL_checknumber(L, 4);
136 *rli_element(L) = newvalue;
137 return 0;
140 static int rli_get(lua_State *L)
142 lua_pushnumber(L, *rli_element(L));
143 return 1;
146 static int rli_tostring(lua_State *L)
148 struct rocklua_image *a = rli_checktype(L, 1);
149 lua_pushfstring(L, ROCKLUA_IMAGE ": %dx%d", a->width, a->height);
150 return 1;
153 static const struct luaL_reg rli_lib [] =
155 {"__tostring", rli_tostring},
156 {"set", rli_set},
157 {"get", rli_get},
158 {"width", rli_width},
159 {"height", rli_height},
160 {NULL, NULL}
163 static inline void rli_init(lua_State *L)
165 luaL_newmetatable(L, ROCKLUA_IMAGE);
167 lua_pushstring(L, "__index");
168 lua_pushvalue(L, -2); /* pushes the metatable */
169 lua_settable(L, -3); /* metatable.__index = metatable */
171 luaL_register(L, NULL, rli_lib);
175 * -----------------------------
177 * Rockbox wrappers start here!
179 * -----------------------------
182 #define RB_WRAP(M) static int rock_##M(lua_State *L)
184 /* Helper function for opt_viewport */
185 static void check_tablevalue(lua_State *L, const char* key, int tablepos, void* res, bool unsigned_val)
187 lua_getfield(L, tablepos, key); /* Find table[key] */
189 if(!lua_isnoneornil(L, -1))
191 if(unsigned_val)
192 *(unsigned*)res = luaL_checkint(L, -1);
193 else
194 *(int*)res = luaL_checkint(L, -1);
197 lua_pop(L, 1); /* Pop the value off the stack */
200 static struct viewport* opt_viewport(lua_State *L, int narg, struct viewport* alt)
202 if(lua_isnoneornil(L, narg))
203 return alt;
205 int tablepos = lua_gettop(L);
206 struct viewport *vp;
208 lua_getfield(L, tablepos, "vp"); /* get table['vp'] */
209 if(lua_isnoneornil(L, -1))
211 lua_pop(L, 1); /* Pop nil off stack */
213 vp = (struct viewport*) lua_newuserdata(L, sizeof(struct viewport)); /* Allocate memory and push it as udata on the stack */
214 memset(vp, 0, sizeof(struct viewport)); /* Init viewport values to 0 */
215 lua_setfield(L, tablepos, "vp"); /* table['vp'] = vp (pops value off the stack) */
217 else
219 vp = (struct viewport*) lua_touserdata(L, -1); /* Reuse viewport struct */
220 lua_pop(L, 1); /* We don't need the value on stack */
223 luaL_checktype(L, narg, LUA_TTABLE);
225 check_tablevalue(L, "x", tablepos, &vp->x, false);
226 check_tablevalue(L, "y", tablepos, &vp->y, false);
227 check_tablevalue(L, "width", tablepos, &vp->width, false);
228 check_tablevalue(L, "height", tablepos, &vp->height, false);
229 #ifdef HAVE_LCD_BITMAP
230 check_tablevalue(L, "font", tablepos, &vp->font, false);
231 check_tablevalue(L, "drawmode", tablepos, &vp->drawmode, false);
232 #endif
233 #if LCD_DEPTH > 1
234 check_tablevalue(L, "fg_pattern", tablepos, &vp->fg_pattern, true);
235 check_tablevalue(L, "bg_pattern", tablepos, &vp->bg_pattern, true);
236 #ifdef HAVE_LCD_COLOR
237 check_tablevalue(L, "lss_pattern", tablepos, &vp->lss_pattern, true);
238 check_tablevalue(L, "lse_pattern", tablepos, &vp->lse_pattern, true);
239 check_tablevalue(L, "lst_pattern", tablepos, &vp->lst_pattern, true);
240 #endif
241 #endif
243 return vp;
246 RB_WRAP(set_viewport)
248 struct viewport *vp = opt_viewport(L, 1, NULL);
249 int screen = luaL_optint(L, 2, SCREEN_MAIN);
250 rb->screens[screen]->set_viewport(vp);
251 return 0;
254 RB_WRAP(clear_viewport)
256 int screen = luaL_optint(L, 1, SCREEN_MAIN);
257 rb->screens[screen]->clear_viewport();
258 return 0;
261 #ifdef HAVE_LCD_BITMAP
262 RB_WRAP(lcd_framebuffer)
264 rli_wrap(L, rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT);
265 return 1;
268 RB_WRAP(lcd_mono_bitmap_part)
270 struct rocklua_image *src = rli_checktype(L, 1);
271 int src_x = luaL_checkint(L, 2);
272 int src_y = luaL_checkint(L, 3);
273 int stride = luaL_checkint(L, 4);
274 int x = luaL_checkint(L, 5);
275 int y = luaL_checkint(L, 6);
276 int width = luaL_checkint(L, 7);
277 int height = luaL_checkint(L, 8);
278 int screen = luaL_optint(L, 9, SCREEN_MAIN);
280 rb->screens[screen]->mono_bitmap_part((const unsigned char *)src->data, src_x, src_y, stride, x, y, width, height);
281 return 0;
284 RB_WRAP(lcd_mono_bitmap)
286 struct rocklua_image *src = rli_checktype(L, 1);
287 int x = luaL_checkint(L, 2);
288 int y = luaL_checkint(L, 3);
289 int width = luaL_checkint(L, 4);
290 int height = luaL_checkint(L, 5);
291 int screen = luaL_optint(L, 6, SCREEN_MAIN);
293 rb->screens[screen]->mono_bitmap((const unsigned char *)src->data, x, y, width, height);
294 return 0;
297 #if LCD_DEPTH > 1
298 RB_WRAP(lcd_bitmap_part)
300 struct rocklua_image *src = rli_checktype(L, 1);
301 int src_x = luaL_checkint(L, 2);
302 int src_y = luaL_checkint(L, 3);
303 int stride = luaL_checkint(L, 4);
304 int x = luaL_checkint(L, 5);
305 int y = luaL_checkint(L, 6);
306 int width = luaL_checkint(L, 7);
307 int height = luaL_checkint(L, 8);
308 int screen = luaL_optint(L, 9, SCREEN_MAIN);
310 rb->screens[screen]->bitmap_part(src->data, src_x, src_y, stride, x, y, width, height);
311 return 0;
314 RB_WRAP(lcd_bitmap)
316 struct rocklua_image *src = rli_checktype(L, 1);
317 int x = luaL_checkint(L, 2);
318 int y = luaL_checkint(L, 3);
319 int width = luaL_checkint(L, 4);
320 int height = luaL_checkint(L, 5);
321 int screen = luaL_optint(L, 6, SCREEN_MAIN);
323 rb->screens[screen]->bitmap(src->data, x, y, width, height);
324 return 0;
327 RB_WRAP(lcd_get_backdrop)
329 fb_data* backdrop = rb->lcd_get_backdrop();
330 if(backdrop == NULL)
331 return 0;
332 else
334 rli_wrap(L, backdrop, LCD_WIDTH, LCD_HEIGHT);
335 return 1;
338 #endif /* LCD_DEPTH > 1 */
340 #if LCD_DEPTH == 16
341 RB_WRAP(lcd_bitmap_transparent_part)
343 struct rocklua_image *src = rli_checktype(L, 1);
344 int src_x = luaL_checkint(L, 2);
345 int src_y = luaL_checkint(L, 3);
346 int stride = luaL_checkint(L, 4);
347 int x = luaL_checkint(L, 5);
348 int y = luaL_checkint(L, 6);
349 int width = luaL_checkint(L, 7);
350 int height = luaL_checkint(L, 8);
351 int screen = luaL_optint(L, 9, SCREEN_MAIN);
353 rb->screens[screen]->transparent_bitmap_part(src->data, src_x, src_y, stride, x, y, width, height);
354 return 0;
357 RB_WRAP(lcd_bitmap_transparent)
359 struct rocklua_image *src = rli_checktype(L, 1);
360 int x = luaL_checkint(L, 2);
361 int y = luaL_checkint(L, 3);
362 int width = luaL_checkint(L, 4);
363 int height = luaL_checkint(L, 5);
364 int screen = luaL_optint(L, 6, SCREEN_MAIN);
366 rb->screens[screen]->transparent_bitmap(src->data, x, y, width, height);
367 return 0;
369 #endif /* LCD_DEPTH == 16 */
371 #endif /* defined(LCD_BITMAP) */
373 RB_WRAP(current_tick)
375 lua_pushinteger(L, *rb->current_tick);
376 return 1;
379 #ifdef HAVE_TOUCHSCREEN
380 RB_WRAP(action_get_touchscreen_press)
382 short x, y;
383 int result = rb->action_get_touchscreen_press(&x, &y);
385 lua_pushinteger(L, result);
386 lua_pushinteger(L, x);
387 lua_pushinteger(L, y);
388 return 3;
390 #endif
392 RB_WRAP(kbd_input)
394 luaL_Buffer b;
395 luaL_buffinit(L, &b);
397 const char *input = luaL_optstring(L, 1, NULL);
398 char *buffer = luaL_prepbuffer(&b);
400 if(input != NULL)
401 rb->strlcpy(buffer, input, LUAL_BUFFERSIZE);
402 else
403 buffer[0] = '\0';
405 if(!rb->kbd_input(buffer, LUAL_BUFFERSIZE))
407 luaL_addsize(&b, strlen(buffer));
408 luaL_pushresult(&b);
410 else
411 lua_pushnil(L);
413 return 1;
416 #ifdef HAVE_TOUCHSCREEN
417 RB_WRAP(touchscreen_set_mode)
419 enum touchscreen_mode mode = luaL_checkint(L, 1);
420 rb->touchscreen_set_mode(mode);
421 return 0;
423 #endif
425 RB_WRAP(font_getstringsize)
427 const unsigned char* str = luaL_checkstring(L, 1);
428 int fontnumber = luaL_checkint(L, 2);
429 int w, h;
431 int result = rb->font_getstringsize(str, &w, &h, fontnumber);
432 lua_pushinteger(L, result);
433 lua_pushinteger(L, w);
434 lua_pushinteger(L, h);
436 return 3;
439 #ifdef HAVE_LCD_COLOR
440 RB_WRAP(lcd_rgbpack)
442 int r = luaL_checkint(L, 1);
443 int g = luaL_checkint(L, 2);
444 int b = luaL_checkint(L, 3);
445 int result = LCD_RGBPACK(r, g, b);
446 lua_pushinteger(L, result);
447 return 1;
450 RB_WRAP(lcd_rgbunpack)
452 int rgb = luaL_checkint(L, 1);
453 lua_pushinteger(L, RGB_UNPACK_RED(rgb));
454 lua_pushinteger(L, RGB_UNPACK_GREEN(rgb));
455 lua_pushinteger(L, RGB_UNPACK_BLUE(rgb));
456 return 3;
458 #endif
460 RB_WRAP(read_bmp_file)
462 struct bitmap bm;
463 const char* filename = luaL_checkstring(L, 1);
464 bool dither = luaL_optboolean(L, 2, true);
465 bool transparent = luaL_optboolean(L, 3, false);
466 int format = FORMAT_NATIVE;
468 if(dither)
469 format |= FORMAT_DITHER;
471 if(transparent)
472 format |= FORMAT_TRANSPARENT;
474 int result = rb->read_bmp_file(filename, &bm, 0, format | FORMAT_RETURN_SIZE, NULL);
476 if(result > 0)
478 bm.data = (unsigned char*) rli_alloc(L, bm.width, bm.height);
479 rb->read_bmp_file(filename, &bm, result, format, NULL);
481 return 1;
484 return 0;
487 RB_WRAP(current_path)
489 const char *current_path = get_current_path(L, 1);
490 if(current_path != NULL)
492 lua_pushstring(L, current_path);
493 return 1;
495 else
496 return 0;
499 static void fill_text_message(lua_State *L, struct text_message * message,
500 int pos)
502 int i;
503 luaL_checktype(L, pos, LUA_TTABLE);
504 int n = luaL_getn(L, pos);
505 const char **lines = (const char**) dlmalloc(n * sizeof(const char*));
506 for(i=1; i<=n; i++)
508 lua_rawgeti(L, pos, i);
509 lines[i-1] = luaL_checkstring(L, -1);
510 lua_pop(L, 1);
512 message->message_lines = lines;
513 message->nb_lines = n;
516 RB_WRAP(gui_syncyesno_run)
518 struct text_message main_message, yes_message, no_message;
519 struct text_message *yes = NULL, *no = NULL;
521 fill_text_message(L, &main_message, 1);
522 if(!lua_isnoneornil(L, 2))
523 fill_text_message(L, (yes = &yes_message), 2);
524 if(!lua_isnoneornil(L, 3))
525 fill_text_message(L, (no = &no_message), 3);
527 enum yesno_res result = rb->gui_syncyesno_run(&main_message, yes, no);
529 dlfree(main_message.message_lines);
530 if(yes)
531 dlfree(yes_message.message_lines);
532 if(no)
533 dlfree(no_message.message_lines);
535 lua_pushinteger(L, result);
536 return 1;
539 #define R(NAME) {#NAME, rock_##NAME}
540 static const luaL_Reg rocklib[] =
542 /* Graphics */
543 #ifdef HAVE_LCD_BITMAP
544 R(lcd_framebuffer),
545 R(lcd_mono_bitmap_part),
546 R(lcd_mono_bitmap),
547 #if LCD_DEPTH > 1
548 R(lcd_get_backdrop),
549 R(lcd_bitmap_part),
550 R(lcd_bitmap),
551 #endif
552 #if LCD_DEPTH == 16
553 R(lcd_bitmap_transparent_part),
554 R(lcd_bitmap_transparent),
555 #endif
556 #endif
557 #ifdef HAVE_LCD_COLOR
558 R(lcd_rgbpack),
559 R(lcd_rgbunpack),
560 #endif
562 /* Kernel */
563 R(current_tick),
565 /* Buttons */
566 #ifdef HAVE_TOUCHSCREEN
567 R(action_get_touchscreen_press),
568 R(touchscreen_set_mode),
569 #endif
570 R(kbd_input),
572 R(font_getstringsize),
573 R(read_bmp_file),
574 R(set_viewport),
575 R(clear_viewport),
576 R(current_path),
577 R(gui_syncyesno_run),
579 {"new_image", rli_new},
581 {NULL, NULL}
583 #undef R
584 extern const luaL_Reg rocklib_aux[];
587 #define RB_CONSTANT(x) lua_pushinteger(L, x); lua_setfield(L, -2, #x);
589 ** Open Rockbox library
591 LUALIB_API int luaopen_rock(lua_State *L)
593 luaL_register(L, LUA_ROCKLIBNAME, rocklib);
594 luaL_register(L, LUA_ROCKLIBNAME, rocklib_aux);
596 RB_CONSTANT(HZ);
598 RB_CONSTANT(LCD_WIDTH);
599 RB_CONSTANT(LCD_HEIGHT);
601 RB_CONSTANT(FONT_SYSFIXED);
602 RB_CONSTANT(FONT_UI);
604 #ifdef HAVE_TOUCHSCREEN
605 RB_CONSTANT(TOUCHSCREEN_POINT);
606 RB_CONSTANT(TOUCHSCREEN_BUTTON);
607 #endif
609 RB_CONSTANT(SCREEN_MAIN);
610 #ifdef HAVE_REMOTE_LCD
611 RB_CONSTANT(SCREEN_REMOTE);
612 #endif
614 rli_init(L);
616 return 1;