--- a/main.c Wed Jan 20 21:43:27 2010 +0200
+++ b/main.c Fri Mar 05 19:15:08 2010 +0200
@@ -579,94 +579,109 @@
/// event context
/// Enum, indicating what exactly caused event function firing.
-/// XXX Well, I am not really understand that EVS_* constants mapping semantics,
-/// so, I just provide data, obtained by experiment.
/// G:
static const string2enum_t lua_event_context[] = {
{ "timeout", EVS_CONTEXT_TIMEOUT },
{ "cancel", EVS_CONTEXT_CANCEL },
- { "reject", EVS_CONTEXT_USER },
- { "accept", EVS_CONTEXT_USER + 1 },
+ { "reject", EVS_CONTEXT_REJECT },
+ { "accept", EVS_CONTEXT_ACCEPT },
{ NULL, 0 },
};
typedef struct {
lua_State *L;
int reference;
+ int evid;
} lua_event_callback_t;
static GSList *lua_events = NULL;
+static void lua_event_callback_destroy_notify (gpointer udata)
+{
+ lua_event_callback_t *cb = udata;
+
+ luaL_unref (cb -> L, LUA_REGISTRYINDEX, cb->reference);
+ luaL_unref (cb -> L, LUA_REGISTRYINDEX, cb->evid);
+ luaL_free (cb -> L, cb);
+}
+
/// event function
/// Function to be called, when some event state change occurs
-/// A: event context
-static int lua_event_callback (eviqs *event, int context)
+/// A: event context, string (event args)
+/// R: boolean (if event shoud be preserved)
+static gboolean lua_event_callback (guint context, const gchar *arg, gpointer userdata)
{
- lua_event_callback_t *cb = event->data;
+ lua_event_callback_t *cb = userdata;
lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
luaL_pushenum (cb->L, context, lua_event_context);
- if (lua_pcall (cb->L, 1, 0, 0)) {
+ lua_pushstring (cb -> L, arg);
+ if (lua_pcall (cb->L, 2, 1, 0)) {
scr_LogPrint (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1));
lua_pop (cb->L, 1);
}
- luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
- lua_events = g_slist_remove (lua_events, event);
- evs_del (event->id); // XXX
-
- return 0; // XXX
+ if (lua_toboolean (cb -> L, -1))
+ return TRUE;
+ else {
+ lua_events = g_slist_remove (lua_events, cb); // XXX
+ return FALSE;
+ }
}
/// main.event
/// Creates new event. If called without arguments, returns event id list.
-/// A: event function (optional), integer (expiration timeout, optional), string (description, optional)
+/// A: event function (optional), string (event id), string (description, optional), integer (expiration timeout, optional)
/// R: string (event id) or nothing (creation error) or table (list of event names)
static int lua_main_event (lua_State *L)
{
int top = lua_gettop (L);
if (top > 0) { // Create
- eviqs *event;
lua_event_callback_t *cb;
+ const char *evid = NULL;
int timeout = 0;
- char *desc = NULL;
+ const char *desc = NULL;
luaL_argcheck (L, lua_type (L, 1) == LUA_TFUNCTION, 1, "event function expected");
if (top > 1) {
- timeout = luaL_checkinteger (L, 2);
+ evid = luaL_checkstring (L, 2);
if (top > 2) {
- desc = g_strdup (luaL_checkstring (L, 3)); // g_freed by mcabber
- lua_pop (L, 2);
+ timeout = luaL_checkinteger (L, 3);
+ if (top > 2) {
+ desc = luaL_checkstring (L, 4);
+ lua_pop (L, 3);
+ } else
+ lua_pop (L, 2);
} else
lua_pop (L, 1);
}
- event = evs_new (EVS_TYPE_USER, timeout);
- if (!event)
- return 0;
-
- lua_pushvalue (L, 1);
- cb = g_new (lua_event_callback_t, 1); // g_freed by mcabber
- cb->L = L;
- cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
+ lua_pushvalue (L, 1); // XXX
+ cb = luaL_malloc (L, sizeof (lua_event_callback_t));
+ cb -> L = L;
+ cb -> reference = luaL_ref (L, LUA_REGISTRYINDEX);
+ cb -> evid = LUA_NOREF;
+ lua_events = g_slist_prepend (lua_events, cb);
- event->data = cb;
- event->callback = lua_event_callback;
- event->desc = desc;
+ evid = evs_new (desc, evid, timeout, lua_event_callback, cb, lua_event_callback_destroy_notify);
+ if (!evid) {
+ lua_events = g_slist_remove (lua_events, cb); // XXX
+ return 0;
+ }
- lua_events = g_slist_prepend (lua_events, event);
+ lua_pushstring (L, evid);
+ lua_pushvalue (L, -1);
+ cb -> evid = luaL_ref (L, LUA_REGISTRYINDEX); // XXX
+ return 1;
- lua_pushstring (L, event->id);
- return 1;
} else { // List
- GSList *events = evs_geteventslist (0);
+ GSList *events = evs_geteventslist ();
GSList *event;
lua_newtable (L);
for (event = events; event; event = g_slist_next (event)) {
lua_pushstring (L, event->data);
luaL_ref (L, -2);
- g_free (event->data);
}
g_slist_free (events);
@@ -1321,12 +1336,26 @@
return NULL;
}
-static void lua_events_destroy (eviqs *event, gpointer ignore)
+static void lua_events_cancel (gpointer data, gpointer ignore)
{
- lua_event_callback_t *cb = event->data;
- evs_callback (event->id, EVS_CONTEXT_CANCEL); // ignore
- luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
- evs_del (event->id);
+ lua_event_callback_t *cb = data;
+ const char *evid;
+ if (cb->evid == LUA_NOREF)
+ return;
+ lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->evid);
+ evid = lua_tostring (cb ->L, -1);
+ evs_callback (evid, EVS_CONTEXT_CANCEL, "Module unloading");
+}
+
+static void lua_events_destroy (gpointer data, gpointer ignore)
+{
+ lua_event_callback_t *cb = data;
+ const char *evid;
+ if (cb->evid == LUA_NOREF)
+ return;
+ lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->evid);
+ evid = lua_tostring (cb ->L, -1);
+ evs_del (evid);
}
static void lua_bgreads_destroy (guint source, gpointer ignore)
@@ -1379,6 +1408,7 @@
g_slist_free (lua_timers);
lua_timers = NULL;
+ g_slist_foreach (lua_events, (GFunc) lua_events_cancel, NULL);
g_slist_foreach (lua_events, (GFunc) lua_events_destroy, NULL);
g_slist_free (lua_events);
lua_events = NULL;