diff -r 000000000000 -r 84fdfb0344c9 glib_main_context.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glib_main_context.c Sun Feb 01 21:28:57 2009 +0200 @@ -0,0 +1,248 @@ + +#include +#include +#include + +#include "glib_types.h" + +/// g.main_context +/// Glib main context object. Mainly useful when lua needs to +/// manage glib-based libs. + +/// g.main_context.new +/// Creates new main context object. +/// R: g main context object +static int lglib_main_context_new (lua_State *L) +{ + GMainContext *context = g_main_context_new (); + lglib_main_context_bless (L, context); + g_main_context_unref (context); + return 1; +} + +/// g.main_context.bless +/// Blesses given pointer to g main context object. +/// A: lightuserdata (C g main context object) +/// R: g main context object +static int lglib_main_context_bless_lua (lua_State *L) +{ + luaL_argcheck (L, lua_islightuserdata (L, 1), 1, "g main context lightuserdata expected"); + lglib_main_context_bless (L, lua_touserdata (L, 1)); + return 1; +} + +/// g.main_context.default +/// Returns default main context object. +/// R: g main context object +static int lglib_main_context_default (lua_State *L) +{ + GMainContext *context = g_main_context_default (); + lglib_main_context_bless (L, context); + // XXX g_main_context_unref (context); + return 1; +} + +/// main_context:iteration +/// Performs single full iteration in blocking or non-blocking manner, +/// depending on value of argument. +/// Returns true, if some events have been handled. +/// A: boolean (optional) +/// R: boolean +static int lglib_main_context_iteration (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + int may_block = 0; + if ( lua_gettop (L) > 1 ) { + luaL_checktype (L, 2, LUA_TBOOLEAN); + may_block = lua_toboolean (L, 2); + } + lua_pushboolean (L, g_main_context_iteration (object->main_context, may_block)); + return 1; +} + +/// main_context:pending +/// Indicates, if there are present events in sources. +/// R: boolean +static int lglib_main_context_pending (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + lua_pushboolean (L, g_main_context_pending (object->main_context)); + return 1; +} + +/// main_context:find_source +/// Returns source with given id. +/// A: integer (source id) +/// R: g main context object or nil +static int lglib_main_context_find_source (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + int id = luaL_checkint (L, 2); + GSource *source = g_main_context_find_source_by_id (object->main_context, id); + if (source) { + lglib_source_bless (L, source); + // XXX g_source_unref (source) + } else + lua_pushnil (L); + return 1; +} + +/// main_context:wakeup +/// Awakes main context if it currently poll() ing. +/// XXX Seems to be threading-related routine, how lua will work in this case? +static int lglib_main_context_wakeup (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + g_main_context_wakeup (object->main_context); + return 0; +} + +/// main_context:acquire +/// Tries to own main context. +/// R: boolean (success) +static int lglib_main_context_acquire (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + lua_pushboolean (L, g_main_context_acquire (object->main_context)); + return 1; +} + +/// main_context:release +/// Disowns acquired context. +/// Note: release context as many times, as you acquired it. +static int lglib_main_context_release (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + g_main_context_release (object->main_context); + return 0; +} + +/// main_context:owner +/// Indicates if current thread is owner of context. +/// R: boolean +static int lglib_main_context_owner (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + lua_pushboolean (L, g_main_context_is_owner (object->main_context)); + return 1; +} + +/// main_context:wait +/// For now this will not be implemented, as it requires threading part of glib + +/// WARNING: conventions for next four methods are likely to change +/// as I become more familiar with all that stuff. + +/// main_context:prepare +/// Polling preparation step. +/// R: boolean (indicates readiness for dispatching before polling), integer (priority of most important ready source, if first value is true) +static int lglib_main_context_prepare (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + gint priority; + gboolean ready = g_main_context_prepare (object->main_context, &priority); + lua_pushboolean (L, ready); + if (!ready) + return 1; + lua_pushnumber (L, priority); + return 0; +} + +/// main_context:query +/// Get necessary for polling information. +/// A: integer (maximum priority), integer (number of fds to allocate) +/// R: userdata (GPollFDs), integer (number of fds required), integer (timeout) +static int lglib_main_context_query (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + int priority = luaL_checkint (L, 2); + int nfds = luaL_checkint (L, 3); + gint timeout; + GPollFD *fds = lua_newuserdata (L, sizeof (GPollFD) * nfds); + lua_pushnumber (L, g_main_context_query (object->main_context, priority, &timeout, fds, nfds)); + lua_pushnumber (L, timeout); + return 3; +} + +/// main_context:check +/// Passes results of polling back to main loop. +/// A: integer (priority), userdata (GPollFDs), integer (number of fds) +/// R: boolean (readiness for dispatching) +static int lglib_main_context_check (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + int priority = luaL_checkint (L, 2); + GPollFD *fds = lua_touserdata (L, 3); // FIXME + int nfds = luaL_checkint (L, 4); + lua_pushboolean (L, g_main_context_check (object->main_context, priority, fds, nfds)); + return 1; +} + +/// main_context:dispatch +/// Actually dispatches pending event sources +static int lglib_main_context_dispatch (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + g_main_context_dispatch (object->main_context); + return 0; +} + +/// main_context:poll_function +/// main_context:add_poll +/// main_context:remove_poll +/// Let's delay implementing this until fd objects will be ready... + +/// main_context:pointer +/// Returns pointe to underlying C structure. +/// A: g main context object +/// R: lightuserdata +static int lglib_main_context_pointer (lua_State *L) +{ + lglib_main_context_t *object = luaL_checklglib_main_context (L, 1); + lua_pushlightuserdata (L, object->main_context); + return 1; +} + +static int lglib_main_context_gc (lua_State *L) +{ + lglib_main_context_t *object = lua_touserdata (L, 1); + g_main_context_unref (object->main_context); + return 0; +} + +static const luaL_Reg lglib_main_context_reg_f[] = { + { "new", lglib_main_context_new }, + { "bless", lglib_main_context_bless_lua }, + { "default", lglib_main_context_default }, + { NULL, NULL }, +}; + +static const luaL_Reg lglib_main_context_reg_m[] = { + { "iteration", lglib_main_context_iteration }, + { "pending", lglib_main_context_pending }, + { "find_source", lglib_main_context_find_source }, + { "wakeup", lglib_main_context_wakeup }, + { "acquire", lglib_main_context_acquire }, + { "release", lglib_main_context_release }, + { "owner", lglib_main_context_owner }, + { "prepare", lglib_main_context_prepare }, + { "query", lglib_main_context_query }, + { "check", lglib_main_context_check }, + { "dispatch", lglib_main_context_dispatch }, + { "pointer", lglib_main_context_pointer }, + { "__gc", lglib_main_context_gc }, + { NULL, NULL }, +}; + +int luaopen_glib_main_context (lua_State *L) +{ + luaL_newmetatable (L, "glib.main_context" ); + lua_pushstring (L, "__index"); + lua_pushvalue (L, -2); + lua_settable (L, -3); + luaL_register (L, NULL, lglib_main_context_reg_m); + lua_pop (L, 1); + luaL_register (L, "g.main_context", lglib_main_context_reg_f); + return 1; +} +