/* * neutrino-mp lua to c++ bridge * * (C) 2013 Stefan Seyfried * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "luainstance.h" #define DBG printf #define lua_boxpointer(L, u) \ (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u)) #define lua_unboxpointer(L, i) \ (*(void **)(lua_touserdata(L, i))) const char CLuaInstance::className[] = "neutrino"; CLuaInstance::CLuaInstance() { /* Create the intepreter object. */ lua = luaL_newstate(); /* register standard + custom functions. */ registerFunctions(); } CLuaInstance::~CLuaInstance() { if (lua != NULL) { lua_close(lua); lua = NULL; } } #define SET_VAR1(NAME) \ lua_pushinteger(lua, NAME); \ lua_setglobal(lua, #NAME); #define SET_VAR2(NAME, VALUE) \ lua_pushinteger(lua, VALUE); \ lua_setglobal(lua, #NAME); #define SET_FONT(NAME) \ lua_pushinteger(lua, SNeutrinoSettings::NAME); \ lua_setglobal(lua, #NAME); /* Run the given script. */ void CLuaInstance::runScript(const char *fileName) { // luaL_dofile(lua, fileName); /* run the script */ int status = luaL_loadfile(lua, fileName); if (status) { fprintf(stderr, "[CLuaInstance::%s] Can't load file: %s\n", __func__, lua_tostring(lua, -1)); return; } /* set variables */ SET_VAR1(COL_COLORED_EVENTS_CHANNELLIST); SET_VAR1(COL_COLORED_EVENTS_INFOBAR); SET_VAR1(COL_INFOBAR_SHADOW); SET_VAR1(COL_INFOBAR); SET_VAR1(COL_MENUHEAD); SET_VAR1(COL_MENUCONTENT); SET_VAR1(COL_MENUCONTENTDARK); SET_VAR1(COL_MENUCONTENTSELECTED); SET_VAR1(COL_MENUCONTENTINACTIVE); SET_VAR1(COL_BACKGROUND); SET_VAR2(SCREEN_OFF_X, g_settings.screen_StartX); SET_VAR2(SCREEN_OFF_Y, g_settings.screen_StartY); SET_VAR2(SCREEN_END_X, g_settings.screen_EndX); SET_VAR2(SCREEN_END_Y, g_settings.screen_EndY); SET_FONT(FONT_TYPE_MENU); SET_FONT(FONT_TYPE_MENU_TITLE); SET_FONT(FONT_TYPE_MENU_INFO); SET_FONT(FONT_TYPE_EPG_TITLE); SET_FONT(FONT_TYPE_EPG_INFO1); SET_FONT(FONT_TYPE_EPG_INFO2); SET_FONT(FONT_TYPE_EPG_DATE); SET_FONT(FONT_TYPE_EVENTLIST_TITLE); SET_FONT(FONT_TYPE_EVENTLIST_ITEMLARGE); SET_FONT(FONT_TYPE_EVENTLIST_ITEMSMALL); SET_FONT(FONT_TYPE_EVENTLIST_DATETIME); SET_FONT(FONT_TYPE_GAMELIST_ITEMLARGE); SET_FONT(FONT_TYPE_GAMELIST_ITEMSMALL); SET_FONT(FONT_TYPE_CHANNELLIST); SET_FONT(FONT_TYPE_CHANNELLIST_DESCR); SET_FONT(FONT_TYPE_CHANNELLIST_NUMBER); SET_FONT(FONT_TYPE_CHANNELLIST_EVENT); SET_FONT(FONT_TYPE_CHANNEL_NUM_ZAP); SET_FONT(FONT_TYPE_INFOBAR_NUMBER); SET_FONT(FONT_TYPE_INFOBAR_CHANNAME); SET_FONT(FONT_TYPE_INFOBAR_INFO); SET_FONT(FONT_TYPE_INFOBAR_SMALL); SET_FONT(FONT_TYPE_FILEBROWSER_ITEM); SET_FONT(FONT_TYPE_MENU_HINT); status = lua_pcall(lua, 0, LUA_MULTRET, 0); if (status) fprintf(stderr, "[CLuaInstance::%s] error in script: %s\n", __func__, lua_tostring(lua, -1)); } const luaL_Reg CLuaInstance::methods[] = { { "PaintBox", CLuaInstance::PaintBox }, { "RenderString", CLuaInstance::RenderString }, { "PaintIcon", CLuaInstance::PaintIcon }, { NULL, NULL } }; /* load basic functions and register our own C callbacks */ void CLuaInstance::registerFunctions() { luaL_openlibs(lua); luaopen_table(lua); luaopen_io(lua); luaopen_string(lua); luaopen_math(lua); lua_newtable(lua); int methodtable = lua_gettop(lua); luaL_newmetatable(lua, className); int metatable = lua_gettop(lua); lua_pushliteral(lua, "__metatable"); lua_pushvalue(lua, methodtable); lua_settable(lua, metatable); lua_pushliteral(lua, "__index"); lua_pushvalue(lua, methodtable); lua_settable(lua, metatable); lua_pushliteral(lua, "__gc"); lua_pushcfunction(lua, GCWindow); lua_settable(lua, metatable); lua_pop(lua, 1); luaL_setfuncs(lua, methods, 0); lua_pop(lua, 1); lua_register(lua, className, NewWindow); } CFBWindow *CLuaInstance::CheckWindow(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TUSERDATA); void *ud = luaL_checkudata(L, narg, className); if (!ud) fprintf(stderr, "[CLuaInstance::%s] wrong type %p, %d, %s\n", __func__, L, narg, className); return *(CFBWindow **)ud; // unbox pointer } int CLuaInstance::NewWindow(lua_State *L) { int count = lua_gettop(L); int x = g_settings.screen_StartX; int y = g_settings.screen_StartY; int w = g_settings.screen_EndX - x; int h = g_settings.screen_EndY - y; if (count > 0) x = luaL_checkint(L, 1); if (count > 1) y = luaL_checkint(L, 2); if (count > 2) w = luaL_checkint(L, 3); if (count > 3) h = luaL_checkint(L, 4); CFBWindow *W = new CFBWindow(x, y, w, h); lua_boxpointer(L, W); luaL_getmetatable(L, className); lua_setmetatable(L, -2); return 1; } int CLuaInstance::PaintBox(lua_State *L) { DBG("CLuaInstance::%s %d\n", __func__, lua_gettop(L)); int x, y, w, h; unsigned int c; CFBWindow *W = CheckWindow(L, 1); if (!W) return 0; x = luaL_checkint(L, 2); y = luaL_checkint(L, 3); w = luaL_checkint(L, 4); h = luaL_checkint(L, 5); c = luaL_checkint(L, 6); /* those checks should be done in CFBWindow instead... */ if (x < 0) x = 0; if (y < 0) y = 0; if (w < 0 || x + w > W->dx) w = W->dx - x; if (h < 0 || y + h > W->dy) h = W->dy - y; /* use the color constants */ c = CFrameBuffer::getInstance()->realcolor[c & 0xff]; W->paintBoxRel(x, y, w, h, c); return 0; } int CLuaInstance::PaintIcon(lua_State *L) { DBG("CLuaInstance::%s %d\n", __func__, lua_gettop(L)); int x, y, h; unsigned int o; const char *fname; CFBWindow *W = CheckWindow(L, 1); if (!W) return 0; fname = luaL_checkstring(L, 2); x = luaL_checkint(L, 3); y = luaL_checkint(L, 4); h = luaL_checkint(L, 5); o = luaL_checkint(L, 6); W->paintIcon(fname, x, y, h, o); return 0; } int CLuaInstance::RenderString(lua_State *L) { int x, y, w, boxh, utf8, f; unsigned int c; const char *text; int numargs = lua_gettop(L); DBG("CLuaInstance::%s %d\n", __func__, numargs); c = COL_MENUCONTENT; boxh = 0; utf8 = 1; CFBWindow *W = CheckWindow(L, 1); if (!W) return 0; f = luaL_checkint(L, 2); /* font number, use FONT_TYPE_XXX in the script */ text = luaL_checkstring(L, 3); /* text */ x = luaL_checkint(L, 4); y = luaL_checkint(L, 5); if (numargs > 5) c = luaL_checkint(L, 6); if (numargs > 6) w = luaL_checkint(L, 7); else w = W->dx - x; if (numargs > 7) boxh = luaL_checkint(L, 8); if (numargs > 8) utf8 = luaL_checkint(L, 9); if (f >= FONT_TYPE_COUNT || f < 0) f = SNeutrinoSettings::FONT_TYPE_MENU; W->RenderString(g_Font[f], x, y, w, text, c, boxh, utf8); return 0; } int CLuaInstance::GCWindow(lua_State *L) { DBG("CLuaInstance::%s %d\n", __func__, lua_gettop(L)); CFBWindow *w = (CFBWindow *)lua_unboxpointer(L, 1); delete w; return 0; }