/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set et sw=2 ts=2: */ /*************************************************************************** * luascript.cc * * Tue Jan 10 14:43:39 CET 2012 * Copyright 2012 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of Pracro. * * Pracro 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. * * Pracro 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 Pracro; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "luascript.h" #include // For atoi #include #include //#include "luautil.h" #define GLOBAL_POINTER "_pracroGlobalLUAObjectPointerThisShouldBeANameThatIsNotAccidentallyOverwritten" #define DEBUG(x, fmt...) printf(fmt) #define ERR(x, fmt...) printf(fmt) static int _debug(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); std::string msg = lua_tostring(L, lua_gettop(L)); printf("%s\n", msg.c_str()); return 0; } static int _forward(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); double x = lua_tonumber(L, lua_gettop(L)); printf("forward %f\n", x); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } if(lua->lua_stop) { printf("stopping...\n"); lua_pushstring(L, "stop"); lua_error(L); } lua->out.forward(x * 5); return 0; } static int _coord(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } if(lua->lua_stop) { printf("stopping...\n"); lua_pushstring(L, "stop"); lua_error(L); } lua_pushnumber(L, lua->out.coordX()); lua_pushnumber(L, lua->out.coordY()); return 2; } static int _loadpen(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); const char *pen = lua_tostring(L, lua_gettop(L)); printf("load pen %s\n", pen); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } if(lua->lua_stop) { printf("stopping...\n"); lua_pushstring(L, "stop"); lua_error(L); } lua->out.loadPen(pen); return 0; } static int _speed(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); int x = lua_tonumber(L, lua_gettop(L)); printf("speed %d\n", x); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } if(lua->lua_stop) { printf("stopping...\n"); lua_pushstring(L, "stop"); lua_error(L); } lua->out.setSpeed(x); return 0; } static int _sleep(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); int s = lua_tonumber(L, lua_gettop(L)); printf("sleep %d\n", s); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); lua->sleep(s); return 0; } static int _colour(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); int r = luaL_checknumber(L, 1); int g = luaL_checknumber(L, 2); int b = luaL_checknumber(L, 3); int a = luaL_checknumber(L, 4); printf("colour %d %d %d %d\n", r,b,g,a); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } if(lua->lua_stop) { printf("stopping...\n"); lua_pushstring(L, "stop"); lua_error(L); } lua->out.setColour(r,g,b,a); return 0; } static int _turn(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); double x = lua_tonumber(L, lua_gettop(L)); printf("turn %f\n", x); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } if(lua->lua_stop) { printf("stopping...\n"); lua_pushstring(L, "stop"); lua_error(L); } lua->out.turn(-x * 10); return 0; } static int _playsound(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); QString file = lua_tostring(L, lua_gettop(L)); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); lua->playSound(file); return 0; } static int _reset(lua_State *L) { //Pracro::checkParameters(L, // Pracro::T_STRING, // Pracro::T_END); printf("reset\n"); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return 1; } if(lua->lua_stop) { lua_pushstring(L, "stop"); lua_error(L); } lua->out.reset(); return 0; } void hook(lua_State *L, lua_Debug *ar) { lua_getinfo(L, "Snl", ar); lua_getglobal(L, GLOBAL_POINTER); LUAScript *lua = (LUAScript*)lua_touserdata(L, lua_gettop(L)); if(!lua) { lua_pushstring(L, "No LUA pointer!"); lua_error(L); return; } //printf("kaiman file: %s\n", lua->file.toStdString().c_str()); if(lua->file == QString(ar->short_src)) { // printf(" ---- currentline: %d\n", ar->currentline); lua->lineChange(ar->currentline); qApp->processEvents(); } //printf("HOOK:\n"); //printf(" what: %s\n", ar->what); //printf(" name: %s\n", ar->name); //printf(" source: %s\n", ar->source); //printf(" short_src: %s\n", ar->short_src); //printf(" currentline: %d\n", ar->currentline); } LUAScript::LUAScript(OutputWindow& o) : out(o) { DEBUG(luascript, "LUAScript()\n"); L = NULL; // Don't call init from here, it need to be done in the thread. lua_stop = true; lua_stopped = true; } LUAScript::~LUAScript() { DEBUG(luascript, "~LUAScript()\n"); } void LUAScript::lineChange(int lineno) { emit lineChanged(lineno); } void LUAScript::init() { if(L) { return; } L = luaL_newstate(); if(L == NULL) { ERR(luascript, "Could not create LUA state.\n"); throw Exception("Could not create LUA state."); } luaL_openlibs(L); lua_pushlightuserdata(L, this); // Push the pointer to 'this' instance lua_setglobal(L, GLOBAL_POINTER); // Assign it to a global lua var. lua_register(L, "debug", _debug); lua_register(L, "forward", _forward); lua_register(L, "turn", _turn); lua_register(L, "speed", _speed); lua_register(L, "reset", _reset); lua_register(L, "colour", _colour); lua_register(L, "loadpen", _loadpen); lua_register(L, "coord", _coord); lua_register(L, "playsound", _playsound); lua_register(L, "sleep", _sleep); lua_sethook(L, hook, LUA_MASKLINE, 0); } void LUAScript::cleanup() { if(L) { lua_close(L); L = NULL; } } void LUAScript::run() { lua_stopped = false; try { init(); runScript(); } catch(Exception &e) { printf("LUA Error: %s\n", e.msg.c_str()); QStringList pieces = QString(e.msg.c_str()).split(":"); if(pieces.size() >= 3) { emit errorLine(pieces[0], pieces[1].toUInt(), pieces[2]); } } cleanup(); lua_stopped = true; printf("LUA Thread Stopped!\n"); } void LUAScript::playSound(QString file) { player.playFile(file); } void LUAScript::stopScript() { lua_stop = true; while(!lua_stopped) { wait(25); qApp->processEvents(); printf("!\n"); } } void LUAScript::runScript() { lua_stop = false; try { init(); } catch(Exception &e) { throw Exception(e.msg); } if(L == NULL) { ERR(luascript, "LUA state not initialized!"); return; } top = lua_gettop(L); // DEBUG(luascript, "Running %s\n", file); if(luaL_loadfile(L, file.toStdString().c_str())) { ERR(luascript, "loadbuffer: %s\n", lua_tostring(L, lua_gettop(L))); throw Exception(lua_tostring(L, lua_gettop(L))); } // Run the loaded code if(lua_pcall(L, 0, LUA_MULTRET, 0)) { ERR(luascript, "pcall: %s\n" , lua_tostring(L, lua_gettop(L))); throw Exception(lua_tostring(L, lua_gettop(L))); } } void LUAScript::setScriptFile(QString file) { this->file = file; } void LUAScript::sleep(int n) { ::sleep(n); }