void event_cb(uint32_t request_id, mrp_resource_set_t *resource_set, void *user_data) { resource_set_lua_t *rset = (resource_set_lua_t *) user_data; mrp_resource_mask_t grant, advice; int top; MRP_UNUSED(request_id); MRP_UNUSED(resource_set); mrp_debug("> event_cb"); top = lua_gettop(rset->L); grant = mrp_get_resource_set_grant(rset->resource_set); advice = mrp_get_resource_set_advice(rset->resource_set); /* update resource set */ rset->acquired = !!grant; rset->available = !!advice; if (mrp_lua_object_deref_value(rset, rset->L, rset->callback, false)) { mrp_lua_push_object(rset->L, rset); if (lua_pcall(rset->L, 1, 0, 0) != 0) mrp_log_error("failed to invoke Lua resource set callback: %s", lua_tostring(rset->L, -1)); } lua_settop(rset->L, top); }
static int resource_set_get_resources(void *data, lua_State *L, int member, mrp_lua_value_t *v) { resource_set_lua_t *rset; void *iter = NULL; mrp_resource_t *resource; mrp_resource_mask_t grant, advice; MRP_UNUSED(member); MRP_UNUSED(v); mrp_debug("> resource_set_get_resources"); rset = (resource_set_lua_t *) data; if (!rset) return luaL_error(L, "internal error"); grant = mrp_get_resource_set_grant(rset->resource_set); advice = mrp_get_resource_set_advice(rset->resource_set); lua_newtable(L); /* push all resource objects to a table and return it */ while ((resource = mrp_resource_set_iterate_resources(rset->resource_set, &iter))) { const char *name = mrp_resource_get_name(resource); mrp_resource_mask_t mask = mrp_resource_get_mask(resource); /* fetch and update the resource object */ resource_lua_t *res = (resource_lua_t *) mrp_htbl_lookup(rset->resources, (void *) name); if (!res) { mrp_log_error("resources out of sync: %s not found", name); continue; } /* mrp_lua_object_ref_value(res, L, 0); */ res->acquired = !!(mask & grant); res->available = !!(mask & advice); /* TODO: update attributes */ /* push the resource to the table */ lua_pushstring(L, res->resource_name); mrp_lua_push_object(L, res); lua_settable(L, -3); } return 1; }
static int resource_get_attributes(void *data, lua_State *L, int member, mrp_lua_value_t *v) { resource_lua_t *res = (resource_lua_t *) data; MRP_UNUSED(member); MRP_UNUSED(v); mrp_debug("> resource_get_attributes"); mrp_lua_push_object(L, res->real_attributes); return 1; }
static int timer_lua_create(lua_State *L) { mrp_context_t *ctx = mrp_lua_get_murphy_context(); char e[128] = ""; timer_lua_t *t; int narg; if (ctx == NULL) luaL_error(L, "failed to get murphy context"); narg = lua_gettop(L); t = (timer_lua_t *)mrp_lua_create_object(L, TIMER_LUA_CLASS, NULL, 0); t->L = L; t->ctx = ctx; t->callback = LUA_NOREF; t->data = LUA_NOREF; switch (narg) { case 1: break; case 2: if (mrp_lua_init_members(t, L, -2, e, sizeof(e)) != 1) return luaL_error(L, "failed to initialize timer members (%s)", e); break; default: return luaL_error(L, "expecting 0 or 1 constructor arguments, " "got %d", narg); } if (t->callback != LUA_NOREF && t->t == NULL) { t->t = mrp_add_timer(t->ctx->ml, t->msecs, timer_lua_cb, t); if (t->t == NULL) { mrp_lua_destroy_object(L, NULL, 0, t); return luaL_error(L, "failed to create Murphy timer"); } } mrp_lua_push_object(L, t); return 1; }
static void timer_lua_cb(mrp_timer_t *timer, void *user_data) { timer_lua_t *t = (timer_lua_t *)user_data; int one = t->oneshot; MRP_UNUSED(timer); if (mrp_lua_object_deref_value(t, t->L, t->callback, false)) { mrp_lua_push_object(t->L, t); mrp_lua_object_deref_value(t, t->L, t->data, true); if (lua_pcall(t->L, 2, 0, 0) != 0) mrp_log_error("failed to invoke Lua timer callback"); } if (one) { mrp_del_timer(t->t); t->t = NULL; } }
static int resource_set_lua_create(lua_State *L) { char e[128] = ""; resource_set_lua_t *rset; int narg; mrp_htbl_config_t conf; mrp_debug("create"); narg = lua_gettop(L); rset = (resource_set_lua_t *) mrp_lua_create_object(L, RESOURCE_SET_LUA_CLASS, NULL, 0); if (!rset) return luaL_error(L, "could not create Lua object"); rset->L = L; /* user can affect these values */ rset->zone = mrp_strdup("default"); rset->application_class = NULL; rset->autorelease = FALSE; rset->dont_wait = FALSE; rset->priority = 0; rset->committed = FALSE; rset->initialized = FALSE; switch (narg) { case 2: /* argument table */ if (mrp_lua_init_members(rset, L, -2, e, sizeof(e)) != 1) return luaL_error(L, "failed to initialize resource members (%s)", e); break; default: return luaL_error(L, "expecting a constructor argument, " "got %d", narg); } if (rset->application_class == NULL) return luaL_error(L, "application_class is a mandatory parameter"); if (rset->priority < 0) rset->priority = 0; /* initial state, these cannot be set by user */ rset->available = FALSE; rset->acquired = FALSE; /* initialize resource map */ conf.nbucket = 0; conf.nentry = 10; conf.comp = mrp_string_comp; conf.hash = mrp_string_hash; conf.free = htbl_free_resource; rset->resources = mrp_htbl_create(&conf); if (!rset->resources) goto error; /* do the actual resource work */ if (!client) { /* create the resource client */ client = mrp_resource_client_create("lua", NULL); if (!client) goto error; } rset->resource_set = mrp_resource_set_create(client, rset->autorelease, rset->dont_wait, rset->priority, event_cb, rset); if (rset->resource_set) n_sets++; else goto error; rset->initialized = TRUE; mrp_lua_push_object(L, rset); return 1; error: return luaL_error(L, "internal resource library error"); }
bool mrp_funcbridge_call_from_c(lua_State *L, mrp_funcbridge_t *fb, const char *signature, mrp_funcbridge_value_t *args, char *ret_type, mrp_funcbridge_value_t *ret_value) { char t; int i; int sp; mrp_funcbridge_value_t *a; int sts; bool success; if (!fb) success = false; else { switch (fb->type) { case MRP_C_FUNCTION: if (!strcmp(signature, fb->c.signature)) success = fb->c.func(L, fb->c.data, signature, args, ret_type, ret_value); else { *ret_type = MRP_FUNCBRIDGE_STRING; ret_value->string = mrp_strdup("mismatching signature " "@ C invocation"); success = false; } break; case MRP_LUA_FUNCTION: sp = lua_gettop(L); mrp_funcbridge_push(L, fb); lua_rawgeti(L, -1, 1); luaL_checktype(L, -1, LUA_TFUNCTION); for (i = 0; (t = signature[i]); i++) { a = args + i; switch (t) { case MRP_FUNCBRIDGE_STRING: lua_pushstring(L, a->string); break; case MRP_FUNCBRIDGE_INTEGER: lua_pushinteger(L, a->integer); break; case MRP_FUNCBRIDGE_FLOATING: lua_pushnumber(L, a->floating); break; case MRP_FUNCBRIDGE_BOOLEAN: lua_pushboolean(L, a->boolean); break; case MRP_FUNCBRIDGE_OBJECT: mrp_lua_push_object(L, a->pointer); break; default: success = false; goto done; } } sts = lua_pcall(L, i, 1, 0); MRP_ASSERT(!sts || (sts && lua_type(L, -1) == LUA_TSTRING), "lua pcall did not return error string when failed"); switch (lua_type(L, -1)) { case LUA_TSTRING: *ret_type = MRP_FUNCBRIDGE_STRING; ret_value->string = mrp_strdup(lua_tolstring(L, -1, NULL)); break; case LUA_TNUMBER: *ret_type = MRP_FUNCBRIDGE_FLOATING; ret_value->floating = lua_tonumber(L, -1); break; case LUA_TBOOLEAN: *ret_type = MRP_FUNCBRIDGE_BOOLEAN; ret_value->boolean = lua_toboolean(L, -1); break; default: *ret_type = MRP_FUNCBRIDGE_NO_DATA; memset(ret_value, 0, sizeof(*ret_value)); break; } success = !sts; done: lua_settop(L, sp); break; default: success = false; break; } } return success; }