Files
neutrino/src/gui/luainstance.cpp
2014-01-19 20:57:35 +01:00

288 lines
7.2 KiB
C++

/*
* neutrino-mp lua to c++ bridge
*
* (C) 2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <global.h>
#include <system/settings.h>
#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;
}