main.c
changeset 92 5d691423c8a6
parent 88 9b5c2357fad7
child 93 0a10228296c1
equal deleted inserted replaced
91:37968123db86 92:5d691423c8a6
   577 
   577 
   578 // MCABBER EVENTS
   578 // MCABBER EVENTS
   579 
   579 
   580 /// event context
   580 /// event context
   581 /// Enum, indicating what exactly caused event function firing.
   581 /// Enum, indicating what exactly caused event function firing.
   582 /// XXX Well, I am not really understand that EVS_* constants mapping semantics,
       
   583 ///     so, I just provide data, obtained by experiment.
       
   584 /// G:
   582 /// G:
   585 static const string2enum_t lua_event_context[] = {
   583 static const string2enum_t lua_event_context[] = {
   586 	{ "timeout", EVS_CONTEXT_TIMEOUT  },
   584 	{ "timeout", EVS_CONTEXT_TIMEOUT  },
   587 	{ "cancel",  EVS_CONTEXT_CANCEL   },
   585 	{ "cancel",  EVS_CONTEXT_CANCEL   },
   588 	{ "reject",  EVS_CONTEXT_USER     },
   586 	{ "reject",  EVS_CONTEXT_REJECT   },
   589 	{ "accept",  EVS_CONTEXT_USER + 1 },
   587 	{ "accept",  EVS_CONTEXT_ACCEPT   },
   590 	{ NULL,      0                    },
   588 	{ NULL,      0                    },
   591 };
   589 };
   592 
   590 
   593 typedef struct {
   591 typedef struct {
   594 	lua_State *L;
   592 	lua_State *L;
   595 	int        reference;
   593 	int        reference;
       
   594 	int        evid;
   596 } lua_event_callback_t;
   595 } lua_event_callback_t;
   597 
   596 
   598 static GSList *lua_events = NULL;
   597 static GSList *lua_events = NULL;
       
   598 
       
   599 static void lua_event_callback_destroy_notify (gpointer udata)
       
   600 {
       
   601 	lua_event_callback_t *cb = udata;
       
   602 
       
   603 	luaL_unref (cb -> L, LUA_REGISTRYINDEX, cb->reference);
       
   604 	luaL_unref (cb -> L, LUA_REGISTRYINDEX, cb->evid);
       
   605 	luaL_free  (cb -> L, cb);
       
   606 }
   599 
   607 
   600 /// event function
   608 /// event function
   601 /// Function to be called, when some event state change occurs
   609 /// Function to be called, when some event state change occurs
   602 /// A: event context
   610 /// A: event context, string (event args)
   603 static int lua_event_callback (eviqs *event, int context)
   611 /// R: boolean (if event shoud be preserved)
   604 {
   612 static gboolean lua_event_callback (guint context, const gchar *arg, gpointer userdata)
   605 	lua_event_callback_t *cb = event->data;
   613 {
       
   614 	lua_event_callback_t *cb = userdata;
   606 
   615 
   607 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   616 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   608 	luaL_pushenum (cb->L, context, lua_event_context);
   617 	luaL_pushenum (cb->L, context, lua_event_context);
   609 	if (lua_pcall (cb->L, 1, 0, 0)) {
   618 	lua_pushstring (cb -> L, arg);
       
   619 	if (lua_pcall (cb->L, 2, 1, 0)) {
   610 		scr_LogPrint (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1));
   620 		scr_LogPrint (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1));
   611 		lua_pop (cb->L, 1);
   621 		lua_pop (cb->L, 1);
   612 	}
   622 	}
   613 
   623 
   614 	luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
   624 	if (lua_toboolean (cb -> L, -1))
   615 	lua_events = g_slist_remove (lua_events, event);
   625 		return TRUE;
   616 	evs_del (event->id); // XXX
   626 	else {
   617 
   627 		lua_events = g_slist_remove (lua_events, cb); // XXX
   618 	return 0; // XXX
   628 		return FALSE;
       
   629 	}
   619 }
   630 }
   620 
   631 
   621 /// main.event
   632 /// main.event
   622 /// Creates new event. If called without arguments, returns event id list.
   633 /// Creates new event. If called without arguments, returns event id list.
   623 /// A: event function (optional), integer (expiration timeout, optional), string (description, optional)
   634 /// A: event function (optional), string (event id), string (description, optional), integer (expiration timeout, optional)
   624 /// R: string (event id) or nothing (creation error) or table (list of event names)
   635 /// R: string (event id) or nothing (creation error) or table (list of event names)
   625 static int lua_main_event (lua_State *L)
   636 static int lua_main_event (lua_State *L)
   626 {
   637 {
   627 	int top = lua_gettop (L);
   638 	int top = lua_gettop (L);
   628 	if (top > 0) { // Create
   639 	if (top > 0) { // Create
   629 		eviqs                *event;
       
   630 		lua_event_callback_t *cb;
   640 		lua_event_callback_t *cb;
       
   641 		const char           *evid    = NULL;
   631 		int                   timeout = 0;
   642 		int                   timeout = 0;
   632 		char                 *desc    = NULL;
   643 		const char           *desc    = NULL;
   633 		luaL_argcheck (L, lua_type (L, 1) == LUA_TFUNCTION, 1, "event function expected");
   644 		luaL_argcheck (L, lua_type (L, 1) == LUA_TFUNCTION, 1, "event function expected");
   634 
   645 
   635 		if (top > 1) {
   646 		if (top > 1) {
   636 			timeout = luaL_checkinteger (L, 2);
   647 			evid = luaL_checkstring (L, 2);
   637 			if (top > 2) {
   648 			if (top > 2) {
   638 				desc = g_strdup (luaL_checkstring (L, 3)); // g_freed by mcabber
   649 				timeout = luaL_checkinteger (L, 3);
   639 				lua_pop (L, 2);
   650 				if (top > 2) {
       
   651 					desc = luaL_checkstring (L, 4);
       
   652 					lua_pop (L, 3);
       
   653 				} else
       
   654 					lua_pop (L, 2);
   640 			} else
   655 			} else
   641 				lua_pop (L, 1);
   656 				lua_pop (L, 1);
   642 		}
   657 		}
   643 
   658 
   644 		event = evs_new (EVS_TYPE_USER, timeout);
   659 		lua_pushvalue (L, 1); // XXX
   645 		if (!event)
   660 		cb              = luaL_malloc (L, sizeof (lua_event_callback_t));
       
   661 		cb -> L         = L;
       
   662 		cb -> reference = luaL_ref (L, LUA_REGISTRYINDEX);
       
   663 		cb -> evid      = LUA_NOREF;
       
   664 		lua_events      = g_slist_prepend (lua_events, cb);
       
   665 
       
   666 		evid = evs_new (desc, evid, timeout, lua_event_callback, cb, lua_event_callback_destroy_notify);
       
   667 		if (!evid) {
       
   668 			lua_events = g_slist_remove (lua_events, cb); // XXX
   646 			return 0;
   669 			return 0;
   647 
   670 		}
   648 		lua_pushvalue (L, 1);
   671 
   649 		cb            = g_new (lua_event_callback_t, 1); // g_freed by mcabber
   672 		lua_pushstring (L, evid);
   650 		cb->L         = L;
   673 		lua_pushvalue (L, -1);
   651 		cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
   674 		cb -> evid = luaL_ref (L, LUA_REGISTRYINDEX); // XXX
   652 
       
   653 		event->data     = cb;
       
   654 		event->callback = lua_event_callback;
       
   655 		event->desc     = desc;
       
   656 
       
   657 		lua_events = g_slist_prepend (lua_events, event);
       
   658 
       
   659 		lua_pushstring (L, event->id);
       
   660 		return 1;
   675 		return 1;
       
   676 
   661 	} else { // List
   677 	} else { // List
   662 		GSList *events = evs_geteventslist (0);
   678 		GSList *events = evs_geteventslist ();
   663 		GSList *event;
   679 		GSList *event;
   664 
   680 
   665 		lua_newtable (L);
   681 		lua_newtable (L);
   666 		for (event = events; event; event = g_slist_next (event)) {
   682 		for (event = events; event; event = g_slist_next (event)) {
   667 			lua_pushstring (L, event->data);
   683 			lua_pushstring (L, event->data);
   668 			luaL_ref (L, -2);
   684 			luaL_ref (L, -2);
   669 			g_free (event->data);
       
   670 		}
   685 		}
   671 		g_slist_free (events);
   686 		g_slist_free (events);
   672 
   687 
   673 		return 1;
   688 		return 1;
   674 	}
   689 	}
  1319 	}
  1334 	}
  1320 
  1335 
  1321 	return NULL;
  1336 	return NULL;
  1322 }
  1337 }
  1323 
  1338 
  1324 static void lua_events_destroy (eviqs *event, gpointer ignore)
  1339 static void lua_events_cancel (gpointer data, gpointer ignore)
  1325 {
  1340 {
  1326 	lua_event_callback_t *cb = event->data;
  1341 	lua_event_callback_t *cb = data;
  1327 	evs_callback (event->id, EVS_CONTEXT_CANCEL); // ignore
  1342 	const char *evid;
  1328 	luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
  1343 	if (cb->evid == LUA_NOREF)
  1329 	evs_del (event->id);
  1344 		return;
       
  1345 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->evid);
       
  1346 	evid = lua_tostring (cb ->L, -1);
       
  1347 	evs_callback (evid, EVS_CONTEXT_CANCEL, "Module unloading");
       
  1348 }
       
  1349 
       
  1350 static void lua_events_destroy (gpointer data, gpointer ignore)
       
  1351 {
       
  1352 	lua_event_callback_t *cb = data;
       
  1353 	const char *evid;
       
  1354 	if (cb->evid == LUA_NOREF)
       
  1355 		return;
       
  1356 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->evid);
       
  1357 	evid = lua_tostring (cb ->L, -1);
       
  1358 	evs_del (evid);
  1330 }
  1359 }
  1331 
  1360 
  1332 static void lua_bgreads_destroy (guint source, gpointer ignore)
  1361 static void lua_bgreads_destroy (guint source, gpointer ignore)
  1333 {
  1362 {
  1334 	g_source_remove (source);
  1363 	g_source_remove (source);
  1377 
  1406 
  1378 		g_slist_foreach (lua_timers, (GFunc) lua_timers_destroy, NULL);
  1407 		g_slist_foreach (lua_timers, (GFunc) lua_timers_destroy, NULL);
  1379 		g_slist_free (lua_timers);
  1408 		g_slist_free (lua_timers);
  1380 		lua_timers = NULL;
  1409 		lua_timers = NULL;
  1381 
  1410 
       
  1411 		g_slist_foreach (lua_events, (GFunc) lua_events_cancel, NULL);
  1382 		g_slist_foreach (lua_events, (GFunc) lua_events_destroy, NULL);
  1412 		g_slist_foreach (lua_events, (GFunc) lua_events_destroy, NULL);
  1383 		g_slist_free (lua_events);
  1413 		g_slist_free (lua_events);
  1384 		lua_events = NULL;
  1414 		lua_events = NULL;
  1385 
  1415 
  1386 		g_slist_foreach (lua_added_features, (GFunc) lua_features_destroy, NULL);
  1416 		g_slist_foreach (lua_added_features, (GFunc) lua_features_destroy, NULL);