From 89433127c43bb9d065a07c0f9124619caa4aaf95 Mon Sep 17 00:00:00 2001 From: bsongis Date: Thu, 12 Jun 2014 18:18:31 +0200 Subject: [PATCH] Lua scripts now in custom functions! --- radio/src/gui/menu_model.cpp | 61 +++++++++------- radio/src/gui/menus.cpp | 13 ++-- radio/src/lcd.cpp | 4 +- radio/src/lua.cpp | 125 ++++++++++++++++++++++++-------- radio/src/mixer.cpp | 2 +- radio/src/myeeprom.h | 2 +- radio/src/opentx.h | 15 +++- radio/src/translations/cz.h.txt | 12 ++- radio/src/translations/de.h.txt | 10 ++- radio/src/translations/en.h.txt | 10 ++- radio/src/translations/es.h.txt | 16 ++-- radio/src/translations/fi.h.txt | 10 ++- radio/src/translations/fr.h.txt | 10 ++- radio/src/translations/it.h.txt | 10 ++- radio/src/translations/pl.h.txt | 10 ++- radio/src/translations/pt.h.txt | 12 ++- radio/src/translations/se.h.txt | 10 ++- 17 files changed, 239 insertions(+), 93 deletions(-) diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index e68356433..454fcb4f1 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -4828,19 +4828,27 @@ void menuModelLogicalSwitches(uint8_t event) void onCustomFunctionsFileSelectionMenu(const char *result) { int8_t sub = m_posVert - 1; + CustomFnData * cf = &g_model.funcSw[sub]; + uint8_t func = CFN_FUNC(cf); if (result == STR_UPDATE_LIST) { char directory[] = SOUNDS_PATH; - strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - if (!listSdFiles(directory, SOUNDS_EXT, sizeof(g_model.funcSw[sub].play.name), NULL)) { - POPUP_WARNING(STR_NO_SOUNDS_ON_SD); + if (func == FUNC_PLAY_SCRIPT) + strcpy(directory, SCRIPTS_PATH); + else + strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); + if (!listSdFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cf->play.name), NULL)) { + POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD); s_menu_flags = 0; } } else { - // The user choosed a wav file in the list - memcpy(g_model.funcSw[sub].play.name, result, sizeof(g_model.funcSw[sub].play.name)); + // The user choosed a file in the list + memcpy(cf->play.name, result, sizeof(cf->play.name)); eeDirty(EE_MODEL); + if (func == FUNC_PLAY_SCRIPT) { + LUA_LOAD_MODEL_SCRIPTS(); + } } } #endif @@ -4874,7 +4882,6 @@ void onCustomFunctionsMenu(const char *result) eeDirty(EE_MODEL); } } - #endif void menuModelCustomFunctions(uint8_t event) @@ -5018,7 +5025,7 @@ void menuModelCustomFunctions(uint8_t event) } #endif #if defined(CPUARM) && defined(SDCARD) - else if (func == FUNC_PLAY_TRACK || func == FUNC_BACKGND_MUSIC) { + else if (func == FUNC_PLAY_TRACK || func == FUNC_BACKGND_MUSIC || func == FUNC_PLAY_SCRIPT) { #if LCD_W >= 212 xcoord_t x = MODEL_CUSTOM_FUNC_3RD_COLUMN; #else @@ -5031,12 +5038,15 @@ void menuModelCustomFunctions(uint8_t event) if (active && event==EVT_KEY_BREAK(KEY_ENTER)) { s_editMode = 0; char directory[] = SOUNDS_PATH; - strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - if (listSdFiles(directory, SOUNDS_EXT, sizeof(sd->play.name), sd->play.name)) { + if (func==FUNC_PLAY_SCRIPT) + strcpy(directory, SCRIPTS_PATH); + else + strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); + if (listSdFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(sd->play.name), sd->play.name)) { menuHandler = onCustomFunctionsFileSelectionMenu; } else { - POPUP_WARNING(STR_NO_SOUNDS_ON_SD); + POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD); s_menu_flags = 0; } } @@ -5235,7 +5245,7 @@ void menuModelCustomScriptOne(uint8_t event) putsStrIdx(lcdLastPos+FW, 0, "LUA", s_currIdx+1, 0); - SUBMENU_NOTITLE(3+scriptInternalData[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); + SUBMENU_NOTITLE(3+scriptInputsOutputs[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); int8_t sub = m_posVert; @@ -5268,32 +5278,32 @@ void menuModelCustomScriptOne(uint8_t event) else if (i == ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL) { lcd_putsLeft(y, STR_INPUTS); } - else if (i <= ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL+scriptInternalData[s_currIdx].inputsCount) { + else if (i <= ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL+scriptInputsOutputs[s_currIdx].inputsCount) { int inputIdx = i-ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL-1; - lcd_putsnAtt(INDENT_WIDTH, y, scriptInternalData[s_currIdx].inputs[inputIdx].name, 10, 0); - if (scriptInternalData[s_currIdx].inputs[inputIdx].type == 0) { - lcd_outdezAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr|LEFT); + lcd_putsnAtt(INDENT_WIDTH, y, scriptInputsOutputs[s_currIdx].inputs[inputIdx].name, 10, 0); + if (scriptInputsOutputs[s_currIdx].inputs[inputIdx].type == 0) { + lcd_outdezAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInputsOutputs[s_currIdx].inputs[inputIdx].def, attr|LEFT); if (attr) { - CHECK_INCDEC_MODELVAR(event, g_model.scriptsData[s_currIdx].inputs[inputIdx], scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); + CHECK_INCDEC_MODELVAR(event, g_model.scriptsData[s_currIdx].inputs[inputIdx], scriptInputsOutputs[s_currIdx].inputs[inputIdx].min-scriptInputsOutputs[s_currIdx].inputs[inputIdx].def, scriptInputsOutputs[s_currIdx].inputs[inputIdx].max-scriptInputsOutputs[s_currIdx].inputs[inputIdx].def); } } else { - putsMixerSource(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr); + putsMixerSource(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInputsOutputs[s_currIdx].inputs[inputIdx].def, attr); if (attr) { uint8_t *source = (uint8_t *)&g_model.scriptsData[s_currIdx].inputs[inputIdx]; - CHECK_INCDEC_MODELSOURCE(event, *source, scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); + CHECK_INCDEC_MODELSOURCE(event, *source, scriptInputsOutputs[s_currIdx].inputs[inputIdx].min-scriptInputsOutputs[s_currIdx].inputs[inputIdx].def, scriptInputsOutputs[s_currIdx].inputs[inputIdx].max-scriptInputsOutputs[s_currIdx].inputs[inputIdx].def); } } } } - if (scriptInternalData[s_currIdx].outputsCount > 0) { + if (scriptInputsOutputs[s_currIdx].outputsCount > 0) { lcd_vline(SCRIPT_ONE_3RD_COLUMN_POS-4, FH+1, LCD_H-FH-1); lcd_puts(SCRIPT_ONE_3RD_COLUMN_POS, FH+1, STR_OUTPUTS); - for (int i=0; i=MIXSRC_FIRST_LUA && source<=MIXSRC_LAST_LUA) { div_t qr = div(source-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); - return (scriptInternalData[qr.quot].state==SCRIPT_OK && qr.rem=MIXSRC_FIRST_LUA && source<=MIXSRC_LAST_LUA) @@ -1568,7 +1563,9 @@ bool isAssignableFunctionAvailable(int function) case FUNC_RESERVE1: case FUNC_RESERVE2: case FUNC_RESERVE3: - case FUNC_RESERVE4: +#if !defined(LUA) + case FUNC_PLAY_SCRIPT: +#endif case FUNC_RESERVE5: return false; diff --git a/radio/src/lcd.cpp b/radio/src/lcd.cpp index 98b69c797..23b14e125 100644 --- a/radio/src/lcd.cpp +++ b/radio/src/lcd.cpp @@ -976,10 +976,10 @@ void putsMixerSource(xcoord_t x, uint8_t y, uint8_t idx, LcdFlags att) else if (idx <= MIXSRC_LAST_LUA) { div_t qr = div(idx-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); #if defined(LUA_MODEL_SCRIPTS) - if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInternalData[qr.quot].outputsCount) { + if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) { lcd_putcAtt(x+2, y+1, '1'+qr.quot, TINSIZE); lcd_filled_rect(x, y, 7, 7); - lcd_putsnAtt(x+8, y, scriptInternalData[qr.quot].outputs[qr.rem].name, att & STREXPANDED ? 9 : 4, att); + lcd_putsnAtt(x+8, y, scriptInputsOutputs[qr.quot].outputs[qr.rem].name, att & STREXPANDED ? 9 : 4, att); } else #endif diff --git a/radio/src/lua.cpp b/radio/src/lua.cpp index 0238225a4..dec138707 100644 --- a/radio/src/lua.cpp +++ b/radio/src/lua.cpp @@ -58,7 +58,9 @@ extern "C" { lua_State *L = NULL; uint8_t luaState = 0; +uint8_t luaScriptsCount = 0; ScriptInternalData scriptInternalData[MAX_SCRIPTS] = { { SCRIPT_NOFILE, 0 } }; +ScriptInputsOutputs scriptInputsOutputs[MAX_SCRIPTS] = { 0 }; ScriptInternalData standaloneScript = { SCRIPT_NOFILE, 0 }; uint16_t maxLuaInterval = 0; uint16_t maxLuaDuration = 0; @@ -915,7 +917,7 @@ static int luaDefaultChannel(lua_State *L) return 1; } -int luaGetInputs(ScriptInternalData & sid) +int luaGetInputs(ScriptInputsOutputs & sid) { if (!lua_istable(L, -1)) return -1; @@ -969,7 +971,7 @@ int luaGetInputs(ScriptInternalData & sid) return 0; } -int luaGetOutputs(ScriptInternalData & sid) +int luaGetOutputs(ScriptInputsOutputs & sid) { if (!lua_istable(L, -1)) return -1; @@ -1107,7 +1109,7 @@ void luaFree(ScriptInternalData & sid) } } -int luaLoad(const char *filename, ScriptInternalData & sid) +int luaLoad(const char *filename, ScriptInternalData & sid, ScriptInputsOutputs * sio=NULL) { int init = 0; @@ -1136,11 +1138,11 @@ int luaLoad(const char *filename, ScriptInternalData & sid) sid.run = luaL_ref(L, LUA_REGISTRYINDEX); lua_pushnil(L); } - else if (!strcmp(key, "input")) { - luaGetInputs(sid); + else if (sio && !strcmp(key, "input")) { + luaGetInputs(*sio); } - else if (!strcmp(key, "output")) { - luaGetOutputs(sid); + else if (sio && !strcmp(key, "output")) { + luaGetOutputs(*sio); } } @@ -1170,26 +1172,65 @@ int luaLoad(const char *filename, ScriptInternalData & sid) void luaLoadModelScript(uint8_t index) { ScriptData & sd = g_model.scriptsData[index]; - ScriptInternalData & sid = scriptInternalData[index]; - - memset(&sid, 0, sizeof(sid)); - sid.state = SCRIPT_NOFILE; if (ZEXIST(sd.file)) { + ScriptInternalData & sid = scriptInternalData[luaScriptsCount++]; + ScriptInputsOutputs * sio = &scriptInputsOutputs[index]; + memset(&sid, 0, sizeof(sid)); + sid.reference = SCRIPT_MIX_FIRST+index; + sid.state = SCRIPT_NOFILE; char filename[sizeof(SCRIPTS_PATH)+sizeof(sd.file)+sizeof(SCRIPTS_EXT)] = SCRIPTS_PATH "/"; strncpy(filename+sizeof(SCRIPTS_PATH), sd.file, sizeof(sd.file)); filename[sizeof(SCRIPTS_PATH)+sizeof(sd.file)] = '\0'; strcat(filename+sizeof(SCRIPTS_PATH), SCRIPTS_EXT); - luaLoad(filename, sid); + luaLoad(filename, sid, sio); } } +bool luaLoadFunctionScript(uint8_t index) +{ + CustomFnData & fn = g_model.funcSw[index]; + + if (fn.func == FUNC_PLAY_SCRIPT && ZEXIST(fn.play.name)) { + if (luaScriptsCount < MAX_SCRIPTS) { + ScriptInternalData & sid = scriptInternalData[luaScriptsCount++]; + memset(&sid, 0, sizeof(sid)); + sid.reference = SCRIPT_FUNC_FIRST+index; + sid.state = SCRIPT_NOFILE; + char filename[sizeof(SCRIPTS_PATH)+sizeof(fn.play.name)+sizeof(SCRIPTS_EXT)] = SCRIPTS_PATH "/"; + strncpy(filename+sizeof(SCRIPTS_PATH), fn.play.name, sizeof(fn.play.name)); + filename[sizeof(SCRIPTS_PATH)+sizeof(fn.play.name)] = '\0'; + strcat(filename+sizeof(SCRIPTS_PATH), SCRIPTS_EXT); + luaLoad(filename, sid); + } + else { + return false; + } + } + + return true; +} + void luaLoadModelScripts() { + luaScriptsCount = 0; + // Load model scripts for (int i=0; i= SCRIPT_MIX_FIRST && sid.reference <= SCRIPT_MIX_LAST) { + ScriptData & sd = g_model.scriptsData[sid.reference-SCRIPT_MIX_FIRST]; + sio = &scriptInputsOutputs[sid.reference-SCRIPT_MIX_FIRST]; + filename = sd.file; + lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); + for (int j=0; jinputsCount; j++) { + if (sio->inputs[j].type == 1) + luaGetValueAndPush((uint8_t)sd.inputs[j]); + else + lua_pushinteger(L, sd.inputs[j] + sio->inputs[j].def); + } } - if (lua_pcall(L, sid.inputsCount, sid.outputsCount, 0) == 0) { - for (int j=sid.outputsCount-1; j>=0; j--) { - if (!lua_isnumber(L, -1)) { - sid.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR); - TRACE("Script %10s disabled", sd.file); - break; + else if (sid.reference >= SCRIPT_FUNC_FIRST && sid.reference <= SCRIPT_FUNC_LAST) { + CustomFnData & fn = g_model.funcSw[sid.reference-SCRIPT_FUNC_FIRST]; + if (!getSwitch(fn.swtch)) { + continue; + } + filename = fn.play.name; + lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); + } +#if 0 + else { + // SCRIPT_TELEMETRY_SCREEN + filename = "telem"; + lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run); + } +#endif + if (lua_pcall(L, sio ? sio->inputsCount : 0, sio ? sio->outputsCount : 0, 0) == 0) { + if (sio) { + for (int j=sio->outputsCount-1; j>=0; j--) { + if (!lua_isnumber(L, -1)) { + sid.state = (instructionsPercent > 100 ? SCRIPT_KILLED : SCRIPT_SYNTAX_ERROR); + TRACE("Script %8s disabled", filename); + break; + } + sio->outputs[j].value = lua_tointeger(L, -1); + lua_pop(L, 1); } - sid.outputs[j].value = lua_tointeger(L, -1); - lua_pop(L, 1); } } else { if (instructionsPercent > 100) { - TRACE("Script %10s killed", sd.file); + TRACE("Script %8s killed", filename); sid.state = SCRIPT_KILLED; } else { - TRACE("Script %10s error: %s", sd.file, lua_tostring(L, -1)); + TRACE("Script %8s error: %s", filename, lua_tostring(L, -1)); sid.state = SCRIPT_SYNTAX_ERROR; } } @@ -1392,6 +1456,7 @@ void luaTask(uint8_t evt) if (max_idx >= 0) { ScriptInternalData & sid = scriptInternalData[max_idx]; TRACE("Script %d killed", max_idx); + // TODO Global Warning sid.state = SCRIPT_LEAK; luaFree(sid); } diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 9551389fd..fc49b866f 100755 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -267,7 +267,7 @@ getvalue_t getValue(uint8_t i) else if (i