~rootmos/lua-hack

f938eaecc76b5afa2d3c2c9d9ba068cb47dc92bb — Gustav Behm 7 months ago a74fe9d
Show notification
2 files changed, 192 insertions(+), 11 deletions(-)

M notify/go.lua
M notify/notify.c
M notify/go.lua => notify/go.lua +2 -2
@@ 1,4 1,4 @@
local N = require("notify")
N.name = "foo"
N.app_name = "foo"

local n = N:new()
N:new{ summary = "hello", body = "foobar", id = 8, timeout = 7000 }:show()

M notify/notify.c => notify/notify.c +190 -9
@@ 63,20 63,199 @@ static int notification_gc(lua_State* L)
    luaR_return(L, 0);
}

static int notification_show(lua_State* L)
{
    luaR_stack(L);
    struct notification* notification = luaL_checkudata(L, 1, TYPE_NOTIFICATION);

    GError* e = NULL;
    if(!notify_notification_show(notification->n, &e)) {
        luaL_where(L, 1);
        lua_pushfstring(L, "unable to show notification: %s", e->message);
        g_error_free(e);
        lua_concat(L, 2);
        return lua_error(L);
    }

    luaR_return(L, 0);
}

static int notification_index(lua_State* L)
{
    luaR_stack(L);
    struct notification* notification = luaL_checkudata(L, 1, TYPE_NOTIFICATION);
    luaL_checkany(L, 2);

    lua_pushvalue(L, 2);
    if(lua_gettable(L, lua_upvalueindex(1)) != LUA_TNIL) {
        luaR_return(L, 1);
    }
    lua_pop(L, 1);

    lua_pushliteral(L, "summary");
    int r = lua_rawequal(L, 2, -1);
    lua_pop(L, 1);
    if(r) {
        gchar* summary;
        g_object_get(notification->n, "summary", &summary, NULL);
        lua_pushstring(L, summary);
        luaR_return(L, 1);
    }

    lua_pushliteral(L, "body");
    r = lua_rawequal(L, 2, -1);
    lua_pop(L, 1);
    if(r) {
        gchar* body;
        g_object_get(notification->n, "body", &body, NULL);
        lua_pushstring(L, body);
        luaR_return(L, 1);
    }

    lua_pushliteral(L, "app_name");
    r = lua_rawequal(L, 2, -1);
    lua_pop(L, 1);
    if(r) {
        gchar* app_name;
        g_object_get(notification->n, "app-name", &app_name, NULL);
        lua_pushstring(L, app_name);
        luaR_return(L, 1);
    }

    lua_pushliteral(L, "id");
    r = lua_rawequal(L, 2, -1);
    lua_pop(L, 1);
    if(r) {
        gint id;
        g_object_get(notification->n, "id", &id, NULL);
        lua_pushinteger(L, id);
        luaR_return(L, 1);
    }

    lua_pushnil(L);
    luaR_return(L, 1);
}

static int notification_new(lua_State* L)
{
    luaR_stack(L);
    struct notify* notify = luaL_checkudata(L, 1, TYPE_NOTIFY);

    const char* summary = NULL;
    const char* body = NULL;
    const char* app_name = NULL;
    gint timeout = NOTIFY_EXPIRES_DEFAULT;
    gint id = 0;

    for(int arg = 2, t = lua_type(L, arg); t != LUA_TNONE; t = lua_type(L, ++arg)) {
        if(t == LUA_TSTRING) {
            if(summary == NULL) {
                summary = lua_tostring(L, arg);
                if(summary == NULL) {
                    failwith("lua_tostring failed unexpectedly");
                }
                debug("summary: %s", summary);
            } else if(body == NULL) {
                body = lua_tostring(L, arg);
                if(body == NULL) {
                    failwith("lua_tostring failed unexpectedly");
                }
                debug("body: %s", body);
            } else {
                return luaL_argerror(L, arg, "unexpected string argument");
            }
        } else if(t == LUA_TTABLE) {
            int f = lua_getfield(L, arg, "summary");
            if(f == LUA_TSTRING) {
                summary = lua_tostring(L, -1);
                if(summary == NULL) {
                    failwith("lua_tostring failed unexpectedly");
                }
                debug("summary: %s", summary);
            } else if(f != LUA_TNIL) {
                return luaL_argerror(L, arg, "summary field not a string");
            }
            lua_pop(L, 1);

            f = lua_getfield(L, arg, "body");
            if(f == LUA_TSTRING) {
                body = lua_tostring(L, -1);
                if(body == NULL) {
                    failwith("lua_tostring failed unexpectedly");
                }
                debug("body: %s", body);
            } else if(f != LUA_TNIL) {
                return luaL_argerror(L, arg, "body field not a string");
            }
            lua_pop(L, 1);

            f = lua_getfield(L, arg, "app_name");
            if(f == LUA_TSTRING) {
                app_name = lua_tostring(L, -1);
                if(body == NULL) {
                    failwith("lua_tostring failed unexpectedly");
                }
                debug("app name: %s", app_name);
            } else if(f != LUA_TNIL) {
                return luaL_argerror(L, arg, "app_name field not a string");
            }
            lua_pop(L, 1);

            f = lua_getfield(L, arg, "timeout");
            if(f == LUA_TNUMBER) {
                int isnum;
                timeout = lua_tointegerx(L, -1, &isnum);
                if(!isnum) {
                    return luaL_argerror(L, arg, "timeout field not an integer");
                }
                debug("timeout: %d", timeout);
            } else if(f != LUA_TNIL) {
                return luaL_argerror(L, arg, "timeout field not a number");
            }
            lua_pop(L, 1);

            f = lua_getfield(L, arg, "id");
            if(f == LUA_TNUMBER) {
                int isnum;
                id = lua_tointegerx(L, -1, &isnum);
                if(!isnum) {
                    return luaL_argerror(L, arg, "timeout field not an integer");
                }
                debug("timeout: %d", timeout);
            } else if(f != LUA_TNIL) {
                return luaL_argerror(L, arg, "timeout field not a number");
            }
            lua_pop(L, 1);

        } else {
            return luaL_argerror(L, arg, "unexpected argument");
        }
    }

    struct notification* notification = lua_newuserdatauv(L, sizeof(struct notification), 0);
    memset(notification, 0, sizeof(*notification));
    notification_ref(notification);
    notification->notify = notify_ref(notify);

    notification->n = notify_notification_new("hello", NULL, NULL);
    notification->n = notify_notification_new(summary, body, NULL);
    CHECK_NOT(notification->n, NULL, "notify_notification_new");

    notify_notification_set_timeout(notification->n, timeout);
    notify_notification_set_app_name(notification->n, app_name);

    if(id > 0) {
        g_object_set(notification->n, "id", id, NULL);
    }

    if(luaL_newmetatable(L, TYPE_NOTIFICATION)) {
        luaL_Reg l[] = {
            { "show", notification_show },
            { NULL, NULL },
        };
        luaL_newlib(L, l);
        lua_pushcclosure(L, notification_index, 1);
        lua_setfield(L, -2, "__index");

        lua_pushcfunction(L, notification_gc);
        lua_setfield(L, -2, "__gc");
    }


@@ 97,7 276,7 @@ static int notify_index(lua_State* L)
    }
    lua_pop(L, 1);

    lua_pushliteral(L, "name");
    lua_pushliteral(L, "app_name");
    int r = lua_rawequal(L, 2, -1);
    lua_pop(L, 1);
    if(r) {


@@ 116,13 295,13 @@ static int notify_newindex(lua_State* L)
    luaL_checkany(L, 2);
    luaL_checkany(L, 3);

    lua_pushliteral(L, "name");
    lua_pushliteral(L, "app_name");
    int r = lua_rawequal(L, 2, -1);
    lua_pop(L, 1);
    if(r) {
        const char* name = luaL_checkstring(L, 3);
        debug("libnotify; setting app name: %s", name);
        notify_set_app_name(name);
        const char* app_name = luaL_checkstring(L, 3);
        debug("libnotify; setting app name: %s", app_name);
        notify_set_app_name(app_name);
        luaR_return(L, 0);
    }



@@ 138,10 317,12 @@ int luaopen_notify(lua_State* L)
    memset(notify, 0, sizeof(*notify));
    notify_ref(notify);

    if(notify_init("lua") != TRUE) {
        return luaL_error(L, "unable to initialize libnotify");
    if(!notify_is_initted()) {
        if(notify_init("lua") != TRUE) {
            return luaL_error(L, "unable to initialize libnotify");
        }
        debug("libnotify init: %s", notify_get_app_name());
    }
    debug("libnotify init: %s", notify_get_app_name());

    if(luaL_newmetatable(L, TYPE_NOTIFY)) {
        luaL_Reg l[] = {