From 9405ae07513ac7ec315bf59323ec7fb1d8565661 Mon Sep 17 00:00:00 2001 From: Janos Kovacs Date: Fri, 11 Jan 2013 14:27:43 +0200 Subject: [PATCH] lua-decision: add sink.lua --- src/core/lua-decision/element.c | 344 +++++++++++++++++++++++++++++++++++++++- src/core/lua-decision/element.h | 17 +- src/core/lua-utils/object.c | 13 ++ src/core/lua-utils/object.h | 2 + 4 files changed, 362 insertions(+), 14 deletions(-) diff --git a/src/core/lua-decision/element.c b/src/core/lua-decision/element.c index 9924ddc..51e881e 100644 --- a/src/core/lua-decision/element.c +++ b/src/core/lua-decision/element.c @@ -32,9 +32,6 @@ #include #include -#include -#include - #include #include @@ -49,6 +46,7 @@ #define ELEMENT_CLASS MRP_LUA_CLASS(element, lua) +#define SINK_CLASS MRP_LUA_CLASS(sink, lua) #define ELEMENT_INPUT_CLASSID MRP_LUA_CLASSID_ROOT "element_input" #define ELEMENT_OUTPUT_CLASSID MRP_LUA_CLASSID_ROOT "element_output" @@ -70,6 +68,11 @@ enum field_e { INPUTS, OUTPUTS, UPDATE, + OBJECT, + INTERFACE, + PROPERTY, + TYPE, + INITIATE, }; enum input_type_e { @@ -92,6 +95,15 @@ struct mrp_lua_element_s { MRP_LUA_ELEMENT_FIELDS; }; +struct mrp_lua_sink_s { + MRP_LUA_ELEMENT_FIELDS; + const char *object; + const char *interface; + const char *property; + const char *type; + mrp_funcbridge_t *initiate; +}; + static int element_create_from_lua(lua_State *); static int element_getfield(lua_State *); @@ -99,7 +111,15 @@ static int element_setfield(lua_State *); static int element_tostring(lua_State *); static void element_destroy_from_lua(void *); static mrp_lua_element_t *element_check(lua_State *, int); -static void element_install(lua_State *, mrp_lua_element_t *); +static void element_install(lua_State *, void *); + +static int sink_create_from_lua(lua_State *); +static int sink_getfield(lua_State *); +static int sink_setfield(lua_State *); +static int sink_tostring(lua_State *); +static void sink_destroy_from_lua(void *); +static mrp_lua_sink_t *sink_check(lua_State *, int); +static void sink_install(lua_State *, void *); static void element_input_class_create(lua_State *); static int element_input_create_luatbl(lua_State *, int); @@ -121,6 +141,11 @@ MRP_LUA_METHOD_LIST_TABLE ( ); MRP_LUA_METHOD_LIST_TABLE ( + sink_methods, /* methodlist name */ + MRP_LUA_METHOD_CONSTRUCTOR (sink_create_from_lua) +); + +MRP_LUA_METHOD_LIST_TABLE ( element_overrides, /* methodlist name */ MRP_LUA_OVERRIDE_CALL (element_create_from_lua) MRP_LUA_OVERRIDE_GETFIELD (element_getfield) @@ -129,6 +154,14 @@ MRP_LUA_METHOD_LIST_TABLE ( ); MRP_LUA_METHOD_LIST_TABLE ( + sink_overrides, /* methodlist name */ + MRP_LUA_OVERRIDE_CALL (sink_create_from_lua) + MRP_LUA_OVERRIDE_GETFIELD (sink_getfield) + MRP_LUA_OVERRIDE_SETFIELD (sink_setfield) + MRP_LUA_OVERRIDE_STRINGIFY (sink_tostring) +); + +MRP_LUA_METHOD_LIST_TABLE ( element_input_overrides, /* methodlist name */ MRP_LUA_OVERRIDE_GETFIELD (element_input_getfield) MRP_LUA_OVERRIDE_SETFIELD (element_input_setfield) @@ -144,10 +177,20 @@ MRP_LUA_CLASS_DEF ( element_overrides /* override methods */ ); +MRP_LUA_CLASS_DEF ( + sink, /* class name */ + lua, /* constructor name */ + mrp_lua_sink_t, /* userdata type */ + sink_destroy_from_lua, /* userdata destructor */ + sink_methods, /* class methods */ + sink_overrides /* override methods */ +); + void mrp_lua_create_element_class(lua_State *L) { mrp_lua_create_object_class(L, ELEMENT_CLASS); + mrp_lua_create_object_class(L, SINK_CLASS); element_input_class_create(L); } @@ -371,6 +414,8 @@ static int element_create_from_lua(lua_State *L) MRP_LUA_ENTER; el = (mrp_lua_element_t *)mrp_lua_create_object(L, ELEMENT_CLASS, NULL); + el->install = element_install; + table = lua_gettop(L); lua_pushinteger(L, INPUT_IDX); @@ -506,7 +551,7 @@ static int element_update_cb(mrp_scriptlet_t *script, mrp_context_tbl_t *ctbl) if (el->update) { if (!mrp_funcbridge_call_from_c(L, el->update, "o", args, &t, &ret)) { - mrp_log_error("failed to call %s:update method (%s)", + mrp_log_error("failed to call element.lua.%s:update method (%s)", el->name, ret.string); mrp_free((void *)ret.string); return FALSE; @@ -517,7 +562,7 @@ static int element_update_cb(mrp_scriptlet_t *script, mrp_context_tbl_t *ctbl) } -static void element_install(lua_State *L, mrp_lua_element_t *el) +static void element_install(lua_State *L, void *void_el) { static mrp_interpreter_t element_updater = { { NULL, NULL }, @@ -529,6 +574,7 @@ static void element_install(lua_State *L, mrp_lua_element_t *el) NULL }; + mrp_lua_element_t *el = (mrp_lua_element_t *)void_el; mrp_lua_element_input_t *inp; mrp_context_t *ctx; size_t i; @@ -583,6 +629,273 @@ static void element_install(lua_State *L, mrp_lua_element_t *el) MRP_LUA_LEAVE_NOARG; } + +static int sink_create_from_lua(lua_State *L) +{ + mrp_lua_sink_t *sink; + int table; + size_t fldnamlen; + const char *fldnam; + + MRP_LUA_ENTER; + + sink = (mrp_lua_sink_t *)mrp_lua_create_object(L, SINK_CLASS, NULL); + sink->install = sink_install; + + table = lua_gettop(L); + + lua_pushinteger(L, INPUT_IDX); + element_input_create_luatbl(L, table); + lua_rawset(L, table); + + MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) { + + switch (field_name_to_type(fldnam, fldnamlen)) { + + case NAME: + sink->name = mrp_strdup(luaL_checkstring(L, -1)); + break; + + case INPUTS: + sink->inputs = element_input_create_userdata(L, -1, &sink->ninput, + &sink->inpmask); + break; + + case OUTPUTS: + luaL_error(L, "sinks can't have outputs"); + break; + + case OBJECT: + sink->object = mrp_strdup(luaL_checkstring(L, -1)); + break; + + case INTERFACE: + sink->interface = mrp_strdup(luaL_checkstring(L, -1)); + break; + + case PROPERTY: + sink->property = mrp_strdup(luaL_checkstring(L, -1)); + break; + + case TYPE: + sink->type = mrp_strdup(luaL_checkstring(L, -1)); + break; + + case INITIATE: + sink->initiate = mrp_funcbridge_create_luafunc(L, -1); + break; + + case UPDATE: + sink->update = mrp_funcbridge_create_luafunc(L, -1); + break; + + default: + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, table); + break; + } + + } /* MRP_LUA_FOREACH_FIELD */ + + if (!sink->name) + luaL_error(L, "missing mandatory 'name' field"); + if (!sink->inputs || !sink->ninput) + luaL_error(L, "missing or empty manadatory 'input' field"); + if (!sink->update) + luaL_error(L, "missing or invalid mandatory 'update' field"); + + mrp_lua_set_object_name(L, SINK_CLASS, sink->name); + + mrp_debug("sink '%s' created", sink->name); + + if (sink->inpmask == INPUT_MASK(sink->ninput)) + sink_install(L, sink); + + MRP_LUA_LEAVE(1); +} + +static int sink_getfield(lua_State *L) +{ + mrp_lua_sink_t *sink; + field_t fld; + + MRP_LUA_ENTER; + + sink = sink_check(L, 1); + fld = field_check(L, 2, NULL); + lua_pop(L, 1); + + switch (fld) { + case NAME: lua_pushstring(L, sink->name); break; + case INPUTS: lua_rawgeti(L, 1, INPUT_IDX); break; + case OBJECT: lua_pushstring(L, sink->object); break; + case INTERFACE: lua_pushstring(L, sink->interface); break; + case PROPERTY: lua_pushstring(L, sink->property); break; + case TYPE: lua_pushstring(L, sink->type); break; + case UPDATE: mrp_funcbridge_push(L, sink->update); break; + default: lua_pushnil(L); break; + } + + MRP_LUA_LEAVE(1); +} + +static int sink_setfield(lua_State *L) +{ + mrp_lua_sink_t *sink; + + MRP_LUA_ENTER; + + sink = sink_check(L, 1); + luaL_error(L, "'%s' is read-only", sink->name); + + MRP_LUA_LEAVE(0); +} + +static int sink_tostring(lua_State *L) +{ + mrp_lua_sink_t *sink; + + MRP_LUA_ENTER; + + if ((sink = sink_check(L, 1)) && sink->name) + lua_pushstring(L, sink->name); + else + lua_pushstring(L, ""); + + MRP_LUA_LEAVE(1); +} + +static void sink_destroy_from_lua(void *data) +{ + mrp_lua_sink_t *sink = (mrp_lua_sink_t *)data; + + MRP_LUA_ENTER; + + if (sink) { + mrp_free((void *)sink->name); + mrp_free((void *)sink->object); + mrp_free((void *)sink->interface); + mrp_free((void *)sink->property); + mrp_free((void *)sink->type); + } + + MRP_LUA_LEAVE_NOARG; +} + +static mrp_lua_sink_t *sink_check(lua_State *L, int idx) +{ + return (mrp_lua_sink_t *)mrp_lua_check_object(L, SINK_CLASS, idx); +} + +static int sink_update_cb(mrp_scriptlet_t *script, mrp_context_tbl_t *ctbl) +{ + lua_State *L = mrp_lua_get_lua_state(); + mrp_lua_sink_t *sink = (mrp_lua_sink_t *)script->data; + mrp_funcbridge_value_t args[1] = { { .pointer = sink } }; + mrp_funcbridge_value_t ret; + char t; + + MRP_UNUSED(ctbl); + + mrp_debug("'%s'", sink->name); + + if (sink->update) { + if (!mrp_funcbridge_call_from_c(L, sink->update, "o",args, &t,&ret)) { + mrp_log_error("failed to call sink.lua.%s:update method (%s)", + sink->name, ret.string); + mrp_free((void *)ret.string); + return FALSE; + } + } + + return TRUE; +} + +static void sink_install(lua_State *L, void *void_sink) +{ + static mrp_interpreter_t sink_updater = { + { NULL, NULL }, + "sink_updater", + NULL, + NULL, + NULL, + sink_update_cb, + NULL + }; + + mrp_lua_sink_t *sink = (mrp_lua_sink_t *)void_sink; + mrp_context_t *ctx; + mrp_funcbridge_value_t args[1] = { { .pointer = sink } }; + mrp_funcbridge_value_t ret; + char t; + mrp_lua_element_input_t *inp; + size_t i; + char buf[1024], target[1024]; + const char **depends, *d; + char *dep; + int ndepend; + char *p, *e; + size_t len; + + MRP_LUA_ENTER; + + ctx = mrp_lua_get_murphy_context(); + + if (ctx == NULL || ctx->r == NULL) { + mrp_log_error("Invalid or incomplete murphy context"); + return; + } + + if (sink->initiate) { + if (!mrp_funcbridge_call_from_c(L, sink->initiate, "o",args, &t,&ret)){ + mrp_log_error("failed to call sink.lua.%s:initiate method (%s)", + sink->name, ret.string); + mrp_free((void *)ret.string); + return; + } + if (t != MRP_FUNCBRIDGE_BOOLEAN) { + mrp_log_error("sink.lua.%s:initiate returned '%c' type instead of " + "'b' (boolean)", sink->name, t); + return; + } + if (!ret.boolean) { + mrp_log_error("sink.lua.%s:initiate failed", sink->name); + return; + } + } + + depends = alloca(sink->ninput * sizeof(depends[0])); + ndepend = 0; + + for (i = 0, e = (p = buf) + sizeof(buf); i < sink->ninput && p < e; i++){ + inp = sink->inputs + i; + + if (inp->type == SELECT) { + d = mrp_lua_select_name(inp->select); + p += snprintf(p, e-p, " _select_%s", d); + + len = strlen(d) + 7 + 1; + depends[ndepend++] = dep = alloca(len); + sprintf(dep, "_select_%s", d); + } + } + + snprintf(target, sizeof(target), "_sink_%s", sink->name); + + printf("\%s:%s\n\tupdate(%s)\n\n", target, buf, sink->name); + + + if (!mrp_resolver_add_prepared_target(ctx->r, target, depends, ndepend, + &sink_updater, NULL, sink)) + { + printf("Failed to install resolver target for element '%s'.\n", + sink->name); + } + + MRP_LUA_LEAVE_NOARG; +} + static void element_input_class_create(lua_State *L) { /* create a metatable for input's */ @@ -693,7 +1006,7 @@ static int element_input_setfield(lua_State *L) } /* switch type */ if ((el->inpmask |= INPUT_BIT(i)) == INPUT_MASK(el->ninput)) - element_install(L, el); + el->install(L, el); break; } @@ -843,6 +1156,8 @@ static field_t field_name_to_type(const char *name, size_t len) case 4: if (!strcmp(name, "name")) return NAME; + if (!strcmp(name, "type")) + return TYPE; break; case 6: @@ -850,6 +1165,8 @@ static field_t field_name_to_type(const char *name, size_t len) return INPUTS; if (!strcmp(name, "update")) return UPDATE; + if (!strcmp(name, "object")) + return OBJECT; break; case 7: @@ -857,6 +1174,18 @@ static field_t field_name_to_type(const char *name, size_t len) return OUTPUTS; break; + case 8: + if (!strcmp(name, "property")) + return PROPERTY; + if (!strcmp(name, "initiate")) + return INITIATE; + break; + + case 9: + if (!strcmp(name, "interface")) + return INTERFACE; + break; + default: break; } @@ -865,6 +1194,7 @@ static field_t field_name_to_type(const char *name, size_t len) } + /* * Local Variables: * c-basic-offset: 4 diff --git a/src/core/lua-decision/element.h b/src/core/lua-decision/element.h index 92885dd..ee633f9 100644 --- a/src/core/lua-decision/element.h +++ b/src/core/lua-decision/element.h @@ -30,19 +30,22 @@ #ifndef __MURPHY_LUA_ELEMENT_H__ #define __MURPHY_LUA_ELEMENT_H__ +#include #include -#define MRP_LUA_ELEMENT_FIELDS \ - const char *name; \ - mrp_lua_element_mask_t inpmask; \ - size_t ninput; \ - mrp_lua_element_input_t *inputs; \ - size_t noutput; \ - mrp_lua_mdb_table_t **outputs; \ +#define MRP_LUA_ELEMENT_FIELDS \ + const char *name; \ + mrp_lua_element_mask_t inpmask; \ + size_t ninput; \ + mrp_lua_element_input_t *inputs; \ + size_t noutput; \ + mrp_lua_mdb_table_t **outputs; \ + void (*install)(lua_State *, void *); \ mrp_funcbridge_t *update typedef struct mrp_lua_element_s mrp_lua_element_t; +typedef struct mrp_lua_sink_s mrp_lua_sink_t; typedef struct mrp_lua_element_input_s mrp_lua_element_input_t; typedef uint32_t mrp_lua_element_mask_t; diff --git a/src/core/lua-utils/object.c b/src/core/lua-utils/object.c index 6dfc64f..ef3f4ba 100644 --- a/src/core/lua-utils/object.c +++ b/src/core/lua-utils/object.c @@ -295,6 +295,19 @@ int mrp_lua_push_object(lua_State *L, void *data) return 1; } +mrp_lua_classdef_t *mrp_lua_get_object_classdef(void *data) +{ + userdata_t *userdata = (userdata_t *)data - 1; + mrp_lua_classdef_t *def; + + if (!data || userdata != userdata->self || userdata->dead) + def = NULL; + else + def = userdata->def; + + return def; +} + static bool valid_id(const char *id) { diff --git a/src/core/lua-utils/object.h b/src/core/lua-utils/object.h index b27323a..8abadff 100644 --- a/src/core/lua-utils/object.h +++ b/src/core/lua-utils/object.h @@ -141,6 +141,8 @@ void *mrp_lua_check_object(lua_State *L, mrp_lua_classdef_t *def, int argnum); void *mrp_lua_to_object(lua_State *L, mrp_lua_classdef_t *def, int idx); int mrp_lua_push_object(lua_State *L, void *object); +mrp_lua_classdef_t *mrp_lua_get_object_classdef(void *); + #endif /* __MURPHY_LUA_OBJECT_H__ */ -- 2.7.4