You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							222 lines
						
					
					
						
							4.8 KiB
						
					
					
				
			
		
		
	
	
							222 lines
						
					
					
						
							4.8 KiB
						
					
					
				| #include "luavgl.h"
 | |
| #include "private.h"
 | |
| 
 | |
| typedef struct luavgl_timer_s {
 | |
|   lua_State *L;
 | |
|   int ref; /* ref to callback */
 | |
| } luavgl_timer_t;
 | |
| 
 | |
| static lv_timer_t *luavgl_check_timer(lua_State *L, int index)
 | |
| {
 | |
|   lv_timer_t *v = *(lv_timer_t **)luaL_checkudata(L, index, "lv_timer");
 | |
|   return v;
 | |
| }
 | |
| 
 | |
| static void luavgl_timer_cb(lv_timer_t *t)
 | |
| {
 | |
|   luavgl_timer_t *data = t->user_data;
 | |
|   lua_State *L = data->L;
 | |
|   int ref = data->ref;
 | |
|   if (ref == LUA_NOREF) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   int top = lua_gettop(L);
 | |
|   /* stack: 1. function, 2. timer userdata */
 | |
|   lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
 | |
|   lua_pushlightuserdata(L, t);
 | |
|   lua_rawget(L, LUA_REGISTRYINDEX); /* this should not fail*/
 | |
| 
 | |
|   luavgl_pcall_int(L, 1, 0);
 | |
|   lua_settop(L, top);
 | |
| }
 | |
| 
 | |
| static void luavgl_timer_set_cb(void *_t, lua_State *L)
 | |
| {
 | |
|   lv_timer_t *t = _t;
 | |
|   int ref = luavgl_check_continuation(L, -1);
 | |
|   luavgl_timer_t *data = t->user_data;
 | |
| 
 | |
|   if (data->ref != LUA_NOREF) {
 | |
|     luaL_unref(L, LUA_REGISTRYINDEX, data->ref);
 | |
|   }
 | |
|   data->ref = ref;
 | |
| }
 | |
| 
 | |
| static void luavgl_timer_set_paused(lv_timer_t *t, int paused)
 | |
| {
 | |
|   /* pause or resume. */
 | |
|   paused ? lv_timer_pause(t) : lv_timer_resume(t);
 | |
| }
 | |
| 
 | |
| /* clang-format off */
 | |
| static const luavgl_value_setter_t timer_property_table[] = {
 | |
|     { "paused", 0, { .setter = (setter_int_t)luavgl_timer_set_paused } },
 | |
|     { "period", 0, { .setter = (setter_int_t)lv_timer_set_period } },
 | |
|     { "repeat_count", 0, { .setter = (setter_int_t)lv_timer_set_repeat_count } },
 | |
|     { "cb", SETTER_TYPE_STACK, { .setter_stack = luavgl_timer_set_cb } },
 | |
| };
 | |
| 
 | |
| /* clang-format on */
 | |
| 
 | |
| static int timer_set_para_cb(lua_State *L, void *data)
 | |
| {
 | |
|   int ret = luavgl_set_property(L, data, timer_property_table);
 | |
| 
 | |
|   if (ret != 0) {
 | |
|     debug("failed\n");
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| /* setup timer using parameter in table idx */
 | |
| int luavgl_timer_setup(lua_State *L, int idx, lv_timer_t *t)
 | |
| {
 | |
|   luavgl_iterate(L, idx, timer_set_para_cb, t);
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * t = luavgl:timer({timer parameters})
 | |
|  * t:pause()
 | |
|  * t:resume()
 | |
|  * t:ready() -- make it ready right now
 | |
|  *
 | |
|  */
 | |
| static int luavgl_timer_create(lua_State *L)
 | |
| {
 | |
|   luavgl_timer_t *data = malloc(sizeof(luavgl_timer_t));
 | |
|   if (data == NULL) {
 | |
|     return luaL_error(L, "No memory.");
 | |
|   }
 | |
|   data->ref = LUA_NOREF;
 | |
|   data->L = L;
 | |
| 
 | |
|   lv_timer_t *t = lv_timer_create(luavgl_timer_cb, 0, data);
 | |
| 
 | |
|   *(void **)lua_newuserdata(L, sizeof(void *)) = t;
 | |
|   luaL_getmetatable(L, "lv_timer");
 | |
|   lua_setmetatable(L, -2);
 | |
| 
 | |
|   lua_pushlightuserdata(L, t);
 | |
|   lua_pushvalue(L, -2);
 | |
|   lua_rawset(L, LUA_REGISTRYINDEX);
 | |
| 
 | |
|   /* parameter table is on stack[1] */
 | |
|   luavgl_timer_setup(L, 1, t);
 | |
|   lua_remove(L, 1); /* remove it to keep stack balance */
 | |
| 
 | |
|   if (t->period == 0) {
 | |
|     /* if period is not set, then it's paused. */
 | |
|     lv_timer_pause(t);
 | |
|   }
 | |
| 
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| static int luavgl_timer_set(lua_State *L)
 | |
| {
 | |
|   lv_timer_t *t = luavgl_check_timer(L, 1);
 | |
|   if (t == NULL) {
 | |
|     return luaL_argerror(L, 1, "timer is null.");
 | |
|   }
 | |
| 
 | |
|   luavgl_timer_setup(L, 2, t);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static int luavgl_timer_ready(lua_State *L)
 | |
| {
 | |
|   lv_timer_t *t = luavgl_check_timer(L, 1);
 | |
|   if (t == NULL) {
 | |
|     return luaL_argerror(L, 1, "timer is null.");
 | |
|   }
 | |
| 
 | |
|   lv_timer_ready(t);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static int luavgl_timer_resume(lua_State *L)
 | |
| {
 | |
|   lv_timer_t *t = luavgl_check_timer(L, 1);
 | |
|   if (t == NULL) {
 | |
|     return luaL_argerror(L, 1, "timer is null.");
 | |
|   }
 | |
| 
 | |
|   lv_timer_resume(t);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static int luavgl_timer_pause(lua_State *L)
 | |
| {
 | |
|   lv_timer_t *t = luavgl_check_timer(L, 1);
 | |
|   if (t == NULL) {
 | |
|     return luaL_argerror(L, 1, "timer is null.");
 | |
|   }
 | |
| 
 | |
|   lv_timer_pause(t);
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /* remove timer from obj,  */
 | |
| static int luavgl_timer_delete(lua_State *L)
 | |
| {
 | |
|   lv_timer_t *t = luavgl_check_timer(L, 1);
 | |
|   if (t == NULL) {
 | |
|     return luaL_argerror(L, 1, "timer is null.");
 | |
|   }
 | |
| 
 | |
|   luavgl_timer_t *data = t->user_data;
 | |
|   if (data->ref) {
 | |
|     luaL_unref(L, LUA_REGISTRYINDEX, data->ref);
 | |
|     data->ref = LUA_NOREF;
 | |
|   }
 | |
| 
 | |
|   lua_pushlightuserdata(L, t);
 | |
|   lua_pushnil(L);
 | |
|   lua_rawset(L, LUA_REGISTRYINDEX);
 | |
| 
 | |
|   /* we can only release memory in gc, since we need t->use_data */
 | |
|   lv_timer_pause(t);
 | |
| 
 | |
|   debug("delete timer:%p\n", t);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static int luavgl_timer_gc(lua_State *L)
 | |
| {
 | |
|   /* stop timer if not stopped. */
 | |
|   luavgl_timer_delete(L);
 | |
| 
 | |
|   lv_timer_t *t = luavgl_check_timer(L, 1);
 | |
|   free(t->user_data);
 | |
|   lv_timer_del(t);
 | |
| 
 | |
|   debug("gc timer:%p\n", t);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static const luaL_Reg luavgl_timer_methods[] = {
 | |
|     {"set",    luavgl_timer_set   },
 | |
|     {"pause",  luavgl_timer_pause },
 | |
|     {"resume", luavgl_timer_resume},
 | |
|     {"delete", luavgl_timer_delete},
 | |
|     {"ready",  luavgl_timer_ready },
 | |
| 
 | |
|     {NULL,     NULL               }
 | |
| };
 | |
| 
 | |
| static void luavgl_timer_init(lua_State *L)
 | |
| {
 | |
|   luaL_newmetatable(L, "lv_timer");
 | |
| 
 | |
|   lua_pushcfunction(L, luavgl_timer_gc);
 | |
|   lua_setfield(L, -2, "__gc");
 | |
| 
 | |
|   luaL_newlib(L, luavgl_timer_methods); /* methods belong to this type */
 | |
|   lua_setfield(L, -2, "__index");
 | |
| 
 | |
|   lua_pop(L, 1); /* pop __index table */
 | |
| }
 | |
| 
 |