New events interface (ugly, untested)
authorMyhailo Danylenko <isbear@ukrpost.net>
Fri, 05 Mar 2010 19:15:08 +0200
changeset 92 5d691423c8a6
parent 91 37968123db86
child 93 0a10228296c1
New events interface (ugly, untested)
TODO
config.h.in
main.c
--- a/TODO	Wed Jan 20 21:43:27 2010 +0200
+++ b/TODO	Fri Mar 05 19:15:08 2010 +0200
@@ -19,7 +19,6 @@
 tune should set self-song only on reply from server
 test node config
 publish library handlers?
-fix add_feature to 1) not add existing items 2) not add default items
 check all that callbacks for empty 'to' fields in print_info
 reply routine?
 put here mcabber headers snapshot
--- a/config.h.in	Wed Jan 20 21:43:27 2010 +0200
+++ b/config.h.in	Fri Mar 05 19:15:08 2010 +0200
@@ -34,9 +34,6 @@
 // priority of glib event sources for timeout and bgread
 #define MLUA_SOURCE_PRIORITY ( ${ML_SOURCE_PRIORITY} )
 
-// hack for mcabber headers
-#define MODULES_ENABLE
-
 #ifdef DEBUG
 #  include <stdio.h>
 
--- 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;