#include <lua.h>
#include <lauxlib.h>
#include <glib.h>
#include "glib_types.h"
#include "util.h"
/// g.source.bless
/// Blesses given pointer to g source object.
/// A: lightuserdata (pointer to C glib event source object)
/// R: g source object
static int lglib_source_bless_lua (lua_State *L)
{
luaL_argcheck (L, lua_islightuserdata (L, 1), 1, "glib source lightuserdata expected");
lglib_source_bless (L, lua_touserdata (L, 1));
return 1;
}
/// source:context
/// Connects event source to main context or returns context,
/// to which this source is connected.
/// A: lglib main context object
/// R: int (source id, when called with args) or g main context object or nil (if called with no args)
static int lglib_source_context (lua_State *L)
{
lglib_source_t *object = luaL_checklglib_source (L, 1);
if (lua_gettop (L) > 1) { // Attach
lglib_main_context_t *context = luaL_checklglib_main_context (L, 2);
lua_pushnumber (L, g_source_attach (object->source, context->main_context));
} else { // Get
GMainContext *context = g_source_get_context (object->source);
if (context) {
lglib_main_context_bless (L, context);
// XXX g_main_context_unref (context);
} else
lua_pushnil (L);
}
return 1;
}
/// source callback function
/// Does processing of events. Return value indicates, if source should not be destroyed.
/// R: boolean (continue)
static gboolean lglib_source_callback (lglib_callback_t *cb)
{
lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
if (lua_pcall (cb->L, 0, 1, 0)) {
// XXX lua_error (cb->L);
lua_pop (cb->L, 1);
return FALSE;
}
return lua_toboolean (cb->L, -1);
}
/// source:callback
/// Sets callback function for given event source.
/// A: source callback function
static int lglib_source_set_callback (lua_State *L)
{
lglib_source_t *object = luaL_checklglib_source (L, 1);
lglib_callback_t *cb;
luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
cb = luaL_malloc (L, sizeof (lglib_callback_t));
cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
cb->L = L;
g_source_set_callback (object->source, (GSourceFunc)lglib_source_callback,
cb, (GDestroyNotify)lglib_callback_destroy);
return 0;
}
/// source:priority
/// Sets or gets priority of source.
/// A: integer (optional priority)
/// R: integer (when called with no args)
static int lglib_source_priority (lua_State *L)
{
lglib_source_t *object = luaL_checklglib_source (L, 1);
if (lua_gettop (L) > 1) {
g_source_set_priority (object->source, luaL_checkint (L, 2));
return 0;
} else {
lua_pushnumber (L, g_source_get_priority (object->source));
return 1;
}
}
/// source:pointer
/// Returns pointer to underlying C structure.
/// A: g source object
/// R: lightuserdata
static int lglib_source_pointer (lua_State *L)
{
lglib_source_t *object = luaL_checklglib_source (L, 1);
lua_pushlightuserdata (L, object->source);
return 1;
}
static int lglib_source_gc (lua_State *L)
{
lglib_source_t *object = lua_touserdata (L, 1);
g_source_unref (object->source);
return 0;
}
const luaL_Reg lglib_source_reg_f[] = {
{ "bless", lglib_source_bless_lua },
{ NULL, NULL },
};
const luaL_Reg lglib_source_reg_m[] = {
{ "context", lglib_source_context },
{ "priority", lglib_source_priority },
{ "callback", lglib_source_set_callback },
{ "pointer", lglib_source_pointer },
{ "__gc", lglib_source_gc },
{ NULL, NULL },
};
int luaopen_glib_source (lua_State *L)
{
luaL_newmetatable (L, "glib.source");
lua_pushstring (L, "__index");
lua_pushvalue (L, -2);
lua_settable (L, -3);
luaL_register (L, NULL, lglib_source_reg_m);
lua_pop (L, 1);
luaL_register (L, "g.source", lglib_source_reg_f);
return 1;
}