1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
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"
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);
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);
82 a
->data
= &a
->dummy
[0][0];
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
);
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
);
111 static int rli_height(lua_State
*L
)
113 struct rocklua_image
*a
= rli_checktype(L
, 1);
114 lua_pushnumber(L
, a
->height
);
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
;
140 static int rli_get(lua_State
*L
)
142 lua_pushnumber(L
, *rli_element(L
));
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
);
153 static const struct luaL_reg rli_lib
[] =
155 {"__tostring", rli_tostring
},
158 {"width", rli_width
},
159 {"height", rli_height
},
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))
192 *(unsigned*)res
= luaL_checkint(L
, -1);
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
))
205 int tablepos
= lua_gettop(L
);
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) */
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);
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);
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
);
254 RB_WRAP(clear_viewport
)
256 int screen
= luaL_optint(L
, 1, SCREEN_MAIN
);
257 rb
->screens
[screen
]->clear_viewport();
263 int ticks
= luaL_checkint(L
, 1);
264 const char *s
= luaL_checkstring(L
, 2);
265 rb
->splash(ticks
, s
);
276 RB_WRAP(lcd_update_rect
)
278 int x
= luaL_checkint(L
, 1);
279 int y
= luaL_checkint(L
, 2);
280 int width
= luaL_checkint(L
, 3);
281 int height
= luaL_checkint(L
, 4);
282 rb
->lcd_update_rect(x
, y
, width
, height
);
286 RB_WRAP(lcd_clear_display
)
289 rb
->lcd_clear_display();
295 int x
= luaL_checkint(L
, 1);
296 int y
= luaL_checkint(L
, 2);
297 const char* string
= luaL_checkstring(L
, 3);
298 rb
->lcd_putsxy(x
, y
, string
);
304 int x
= luaL_checkint(L
, 1);
305 int y
= luaL_checkint(L
, 2);
306 const char* string
= luaL_checkstring(L
, 3);
307 rb
->lcd_puts(x
, y
, string
);
311 RB_WRAP(lcd_puts_scroll
)
313 int x
= luaL_checkint(L
, 1);
314 int y
= luaL_checkint(L
, 2);
315 const char* string
= luaL_checkstring(L
, 3);
316 rb
->lcd_puts_scroll(x
, y
, string
);
320 RB_WRAP(lcd_stop_scroll
)
323 rb
->lcd_stop_scroll();
327 #ifdef HAVE_LCD_BITMAP
328 RB_WRAP(lcd_framebuffer
)
330 rli_wrap(L
, rb
->lcd_framebuffer
, LCD_WIDTH
, LCD_HEIGHT
);
334 RB_WRAP(lcd_set_drawmode
)
336 int drawmode
= luaL_checkint(L
, 1);
337 rb
->lcd_set_drawmode(drawmode
);
341 RB_WRAP(lcd_get_drawmode
)
343 int result
= rb
->lcd_get_drawmode();
344 lua_pushinteger(L
, result
);
350 int font
= luaL_checkint(L
, 1);
351 rb
->lcd_setfont(font
);
355 RB_WRAP(lcd_drawpixel
)
357 int x
= luaL_checkint(L
, 1);
358 int y
= luaL_checkint(L
, 2);
360 rb
->lcd_drawpixel(x
, y
);
364 RB_WRAP(lcd_drawline
)
366 int x1
= luaL_checkint(L
, 1);
367 int y1
= luaL_checkint(L
, 2);
368 int x2
= luaL_checkint(L
, 3);
369 int y2
= luaL_checkint(L
, 4);
371 rb
->lcd_drawline(x1
, y1
, x2
, y2
);
377 int x1
= luaL_checkint(L
, 1);
378 int x2
= luaL_checkint(L
, 2);
379 int y
= luaL_checkint(L
, 3);
381 rb
->lcd_hline(x1
, x2
, y
);
387 int x
= luaL_checkint(L
, 1);
388 int y1
= luaL_checkint(L
, 2);
389 int y2
= luaL_checkint(L
, 3);
391 rb
->lcd_vline(x
, y1
, y2
);
395 RB_WRAP(lcd_drawrect
)
397 int x
= luaL_checkint(L
, 1);
398 int y
= luaL_checkint(L
, 2);
399 int width
= luaL_checkint(L
, 3);
400 int height
= luaL_checkint(L
, 4);
402 rb
->lcd_drawrect(x
, y
, width
, height
);
406 RB_WRAP(lcd_fillrect
)
408 int x
= luaL_checkint(L
, 1);
409 int y
= luaL_checkint(L
, 2);
410 int width
= luaL_checkint(L
, 3);
411 int height
= luaL_checkint(L
, 4);
413 rb
->lcd_fillrect(x
, y
, width
, height
);
417 RB_WRAP(lcd_mono_bitmap_part
)
419 struct rocklua_image
*src
= rli_checktype(L
, 1);
420 int src_x
= luaL_checkint(L
, 2);
421 int src_y
= luaL_checkint(L
, 3);
422 int stride
= luaL_checkint(L
, 4);
423 int x
= luaL_checkint(L
, 5);
424 int y
= luaL_checkint(L
, 6);
425 int width
= luaL_checkint(L
, 7);
426 int height
= luaL_checkint(L
, 8);
428 rb
->lcd_mono_bitmap_part((const unsigned char *)src
->data
, src_x
, src_y
, stride
, x
, y
, width
, height
);
432 RB_WRAP(lcd_mono_bitmap
)
434 struct rocklua_image
*src
= rli_checktype(L
, 1);
435 int x
= luaL_checkint(L
, 2);
436 int y
= luaL_checkint(L
, 3);
437 int width
= luaL_checkint(L
, 4);
438 int height
= luaL_checkint(L
, 5);
440 rb
->lcd_mono_bitmap((const unsigned char *)src
->data
, x
, y
, width
, height
);
445 RB_WRAP(lcd_set_foreground
)
447 unsigned foreground
= luaL_checkint(L
, 1);
448 rb
->lcd_set_foreground(foreground
);
452 RB_WRAP(lcd_get_foreground
)
454 unsigned result
= rb
->lcd_get_foreground();
455 lua_pushinteger(L
, result
);
459 RB_WRAP(lcd_set_background
)
461 unsigned background
= luaL_checkint(L
, 1);
462 rb
->lcd_set_background(background
);
466 RB_WRAP(lcd_get_background
)
468 unsigned result
= rb
->lcd_get_background();
469 lua_pushinteger(L
, result
);
473 RB_WRAP(lcd_bitmap_part
)
475 struct rocklua_image
*src
= rli_checktype(L
, 1);
476 int src_x
= luaL_checkint(L
, 2);
477 int src_y
= luaL_checkint(L
, 3);
478 int stride
= luaL_checkint(L
, 4);
479 int x
= luaL_checkint(L
, 5);
480 int y
= luaL_checkint(L
, 6);
481 int width
= luaL_checkint(L
, 7);
482 int height
= luaL_checkint(L
, 8);
484 rb
->lcd_bitmap_part(src
->data
, src_x
, src_y
, stride
, x
, y
, width
, height
);
490 struct rocklua_image
*src
= rli_checktype(L
, 1);
491 int x
= luaL_checkint(L
, 2);
492 int y
= luaL_checkint(L
, 3);
493 int width
= luaL_checkint(L
, 4);
494 int height
= luaL_checkint(L
, 5);
496 rb
->lcd_bitmap(src
->data
, x
, y
, width
, height
);
500 RB_WRAP(lcd_get_backdrop
)
502 fb_data
* backdrop
= rb
->lcd_get_backdrop();
507 rli_wrap(L
, backdrop
, LCD_WIDTH
, LCD_HEIGHT
);
511 #endif /* LCD_DEPTH > 1 */
514 RB_WRAP(lcd_bitmap_transparent_part
)
516 struct rocklua_image
*src
= rli_checktype(L
, 1);
517 int src_x
= luaL_checkint(L
, 2);
518 int src_y
= luaL_checkint(L
, 3);
519 int stride
= luaL_checkint(L
, 4);
520 int x
= luaL_checkint(L
, 5);
521 int y
= luaL_checkint(L
, 6);
522 int width
= luaL_checkint(L
, 7);
523 int height
= luaL_checkint(L
, 8);
525 rb
->lcd_bitmap_transparent_part(src
->data
, src_x
, src_y
, stride
, x
, y
, width
, height
);
529 RB_WRAP(lcd_bitmap_transparent
)
531 struct rocklua_image
*src
= rli_checktype(L
, 1);
532 int x
= luaL_checkint(L
, 2);
533 int y
= luaL_checkint(L
, 3);
534 int width
= luaL_checkint(L
, 4);
535 int height
= luaL_checkint(L
, 5);
537 rb
->lcd_bitmap_transparent(src
->data
, x
, y
, width
, height
);
540 #endif /* LCD_DEPTH == 16 */
542 #endif /* defined(LCD_BITMAP) */
553 int ticks
= luaL_checkint(L
, 1);
558 RB_WRAP(current_tick
)
560 lua_pushinteger(L
, *rb
->current_tick
);
566 bool block
= luaL_checkboolean(L
, 1);
567 long result
= rb
->button_get(block
);
568 lua_pushinteger(L
, result
);
572 RB_WRAP(button_get_w_tmo
)
574 int ticks
= luaL_checkint(L
, 1);
575 long result
= rb
->button_get_w_tmo(ticks
);
576 lua_pushinteger(L
, result
);
580 RB_WRAP(button_status
)
582 int result
= rb
->button_status();
583 lua_pushinteger(L
, result
);
587 #ifdef HAVE_BUTTON_DATA
588 RB_WRAP(button_get_data
)
590 int result
= rb
->button_get_data();
591 lua_pushinteger(L
, result
);
596 #ifdef HAS_BUTTON_HOLD
599 bool result
= rb
->button_hold();
600 lua_pushboolean(L
, result
);
607 int context
= luaL_checkint(L
, 1);
608 int timeout
= luaL_checkint(L
, 2);
609 int result
= rb
->get_action(context
, timeout
);
610 lua_pushinteger(L
, result
);
614 #ifdef HAVE_TOUCHSCREEN
615 RB_WRAP(action_get_touchscreen_press
)
618 int result
= rb
->action_get_touchscreen_press(&x
, &y
);
620 lua_pushinteger(L
, result
);
621 lua_pushinteger(L
, x
);
622 lua_pushinteger(L
, y
);
627 RB_WRAP(action_userabort
)
629 int timeout
= luaL_checkint(L
, 1);
630 bool result
= rb
->action_userabort(timeout
);
631 lua_pushboolean(L
, result
);
638 luaL_buffinit(L
, &b
);
640 char *buffer
= luaL_prepbuffer(&b
);
642 rb
->kbd_input(buffer
, LUAL_BUFFERSIZE
);
643 luaL_addsize(&b
, strlen(buffer
));
649 #ifdef HAVE_TOUCHSCREEN
650 RB_WRAP(touchscreen_set_mode
)
652 enum touchscreen_mode mode
= luaL_checkint(L
, 1);
653 rb
->touchscreen_set_mode(mode
);
658 RB_WRAP(backlight_on
)
665 RB_WRAP(backlight_off
)
672 RB_WRAP(backlight_set_timeout
)
674 int val
= luaL_checkint(L
, 1);
675 rb
->backlight_set_timeout(val
);
679 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
680 RB_WRAP(backlight_set_brightness
)
682 int val
= luaL_checkint(L
, 1);
683 rb
->backlight_set_brightness(val
);
690 const char* pathname
= luaL_checkstring(L
, 1);
691 int result
= rb
->creat(pathname
);
692 lua_pushinteger(L
, result
);
698 const char* pathname
= luaL_checkstring(L
, 1);
699 int result
= rb
->remove(pathname
);
700 lua_pushinteger(L
, result
);
706 const char* path
= luaL_checkstring(L
, 1);
707 const char* newname
= luaL_checkstring(L
, 2);
708 int result
= rb
->rename(path
, newname
);
709 lua_pushinteger(L
, result
);
715 const char* path
= luaL_checkstring(L
, 1);
716 bool result
= rb
->file_exists(path
);
717 lua_pushboolean(L
, result
);
721 RB_WRAP(font_getstringsize
)
723 const unsigned char* str
= luaL_checkstring(L
, 1);
724 int fontnumber
= luaL_checkint(L
, 2);
727 int result
= rb
->font_getstringsize(str
, &w
, &h
, fontnumber
);
728 lua_pushinteger(L
, result
);
729 lua_pushinteger(L
, w
);
730 lua_pushinteger(L
, h
);
735 #ifdef HAVE_LCD_COLOR
738 int r
= luaL_checkint(L
, 1);
739 int g
= luaL_checkint(L
, 2);
740 int b
= luaL_checkint(L
, 3);
741 int result
= LCD_RGBPACK(r
, g
, b
);
742 lua_pushinteger(L
, result
);
746 RB_WRAP(lcd_rgbunpack
)
748 int rgb
= luaL_checkint(L
, 1);
749 lua_pushinteger(L
, RGB_UNPACK_RED(rgb
));
750 lua_pushinteger(L
, RGB_UNPACK_GREEN(rgb
));
751 lua_pushinteger(L
, RGB_UNPACK_BLUE(rgb
));
756 RB_WRAP(read_bmp_file
)
759 const char* filename
= luaL_checkstring(L
, 1);
760 bool dither
= luaL_optboolean(L
, 2, true);
761 bool transparent
= luaL_optboolean(L
, 3, false);
762 int format
= FORMAT_NATIVE
;
765 format
|= FORMAT_DITHER
;
768 format
|= FORMAT_TRANSPARENT
;
770 int result
= rb
->read_bmp_file(filename
, &bm
, 0, format
| FORMAT_RETURN_SIZE
, NULL
);
774 bm
.data
= (unsigned char*) rli_alloc(L
, bm
.width
, bm
.height
);
775 rb
->read_bmp_file(filename
, &bm
, result
, format
, NULL
);
783 RB_WRAP(current_path
)
785 char buffer
[MAX_PATH
];
788 if(lua_getstack(L
, 1, &ar
))
790 /* Try determining the base path of the current Lua chunk
791 and write it to dest. */
792 lua_getinfo(L
, "S", &ar
);
794 char* curfile
= (char*) &ar
.source
[1];
795 char* pos
= rb
->strrchr(curfile
, '/');
798 unsigned int len
= (unsigned int)(pos
- curfile
);
799 len
= len
+ 1 > sizeof(buffer
) ? sizeof(buffer
) - 1 : len
;
802 memcpy(buffer
, curfile
, len
);
805 buffer
[len
+1] = '\0';
807 lua_pushstring(L
, buffer
);
815 #define R(NAME) {#NAME, rock_##NAME}
816 static const luaL_Reg rocklib
[] =
819 R(lcd_clear_display
),
827 #ifdef HAVE_LCD_BITMAP
838 R(lcd_mono_bitmap_part
),
841 R(lcd_set_foreground
),
842 R(lcd_get_foreground
),
843 R(lcd_set_background
),
844 R(lcd_get_background
),
850 R(lcd_bitmap_transparent_part
),
851 R(lcd_bitmap_transparent
),
854 #ifdef HAVE_LCD_COLOR
874 #ifdef HAVE_BUTTON_DATA
877 #ifdef HAS_BUTTON_HOLD
882 #ifdef HAVE_TOUCHSCREEN
883 R(action_get_touchscreen_press
),
884 R(touchscreen_set_mode
),
891 R(backlight_set_timeout
),
892 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
893 R(backlight_set_brightness
),
896 R(font_getstringsize
),
902 {"new_image", rli_new
},
908 #define RB_CONSTANT(x) lua_pushinteger(L, x); lua_setfield(L, -2, #x);
910 ** Open Rockbox library
912 LUALIB_API
int luaopen_rock(lua_State
*L
)
914 luaL_register(L
, LUA_ROCKLIBNAME
, rocklib
);
918 RB_CONSTANT(LCD_WIDTH
);
919 RB_CONSTANT(LCD_HEIGHT
);
921 RB_CONSTANT(FONT_SYSFIXED
);
922 RB_CONSTANT(FONT_UI
);
924 #ifdef HAVE_TOUCHSCREEN
925 RB_CONSTANT(TOUCHSCREEN_POINT
);
926 RB_CONSTANT(TOUCHSCREEN_BUTTON
);
927 RB_CONSTANT(BUTTON_TOUCHSCREEN
);
930 RB_CONSTANT(BUTTON_REL
);
931 RB_CONSTANT(BUTTON_REPEAT
);