diff --git a/radio/src/lua/api_colorlcd_lvgl.cpp b/radio/src/lua/api_colorlcd_lvgl.cpp index d6cf9909c..b7b804e78 100644 --- a/radio/src/lua/api_colorlcd_lvgl.cpp +++ b/radio/src/lua/api_colorlcd_lvgl.cpp @@ -47,7 +47,7 @@ static int luaLvglObjEx(lua_State *L, std::function cre LvglWidgetObjectBase* p = nullptr; LvglWidgetObjectBase* prevParent = nullptr; if (lua_gettop(L) == 2) { - p = LvglWidgetObjectBase::checkLvgl(L, 1); + p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { prevParent = luaScriptManager->getTempParent(); luaScriptManager->setTempParent(p); @@ -86,7 +86,7 @@ static int luaDestroyLvglWidget(lua_State *L) static int luaLvglSet(lua_State *L) { - auto p = LvglWidgetObjectBase::checkLvgl(L, 1); + auto p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { p->update(L); } @@ -97,7 +97,7 @@ static int luaLvglClear(lua_State *L) { if (luaScriptManager) { if (lua_gettop(L) == 1) { - auto p = LvglWidgetObjectBase::checkLvgl(L, 1); + auto p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { p->clear(); } @@ -111,7 +111,7 @@ static int luaLvglClear(lua_State *L) static int luaLvglShow(lua_State *L) { - auto p = LvglWidgetObjectBase::checkLvgl(L, 1); + auto p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { p->show(); } @@ -120,7 +120,7 @@ static int luaLvglShow(lua_State *L) static int luaLvglHide(lua_State *L) { - auto p = LvglWidgetObjectBase::checkLvgl(L, 1); + auto p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { p->hide(); } @@ -129,7 +129,7 @@ static int luaLvglHide(lua_State *L) static int luaLvglEnable(lua_State *L) { - auto p = LvglWidgetObjectBase::checkLvgl(L, 1); + auto p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { p->enable(); } @@ -138,7 +138,7 @@ static int luaLvglEnable(lua_State *L) static int luaLvglDisable(lua_State *L) { - auto p = LvglWidgetObjectBase::checkLvgl(L, 1); + auto p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { p->disable(); } @@ -147,7 +147,7 @@ static int luaLvglDisable(lua_State *L) static int luaLvglClose(lua_State *L) { - auto p = LvglWidgetObjectBase::checkLvgl(L, 1); + auto p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { p->close(); } @@ -269,7 +269,7 @@ static int luaLvglBuild(lua_State *L) LvglWidgetObjectBase* p = nullptr; LvglWidgetObjectBase* prevParent = nullptr; if (lua_gettop(L) == 2) { - p = LvglWidgetObjectBase::checkLvgl(L, 1); + p = LvglWidgetObjectBase::checkLvgl(L, 1, true); if (p) { prevParent = luaScriptManager->getTempParent(); luaScriptManager->setTempParent(p); diff --git a/radio/src/lua/lua_lvgl_widget.cpp b/radio/src/lua/lua_lvgl_widget.cpp index a34efc6a6..1a3eec880 100644 --- a/radio/src/lua/lua_lvgl_widget.cpp +++ b/radio/src/lua/lua_lvgl_widget.cpp @@ -112,15 +112,19 @@ static bool pcallFuncWithString(lua_State *L, int funcRef, int nretval, const ch //----------------------------------------------------------------------------- -LvglWidgetObjectBase *LvglWidgetObjectBase::checkLvgl(lua_State *L, int index) +LvglWidgetObjectBase *LvglWidgetObjectBase::checkLvgl(lua_State *L, int index, bool required) { LvglWidgetObjectBase **p; p = (LvglWidgetObjectBase **)luaL_testudata(L, index, LVGL_METATABLE); - if (p) return *p; + if (p && *p) return *p; p = (LvglWidgetObjectBase **)luaL_testudata(L, index, LVGL_SIMPLEMETATABLE); - if (p) return *p; + if (p && *p) return *p; + + if (required) { + luaL_error(L, "Invalid lvgl object (it has been probably been cleared)."); + } return nullptr; } @@ -170,16 +174,18 @@ void LvglWidgetObjectBase::getParams(lua_State *L, int index) void LvglWidgetObjectBase::pcallSimpleFunc(lua_State *L, int funcRef) { if (funcRef != LUA_REFNIL) { + auto save = luaScriptManager; + luaScriptManager = lvglManager; PROTECT_LUA() { - auto save = luaScriptManager; - luaScriptManager = lvglManager; if (!pcallFunc(L, funcRef, 0)) { lvglManager->luaShowError(); } - luaScriptManager = save; + } else { + lvglManager->luaShowError(); } UNPROTECT_LUA(); + luaScriptManager = save; } } @@ -191,18 +197,24 @@ bool LvglWidgetObjectBase::pcallUpdateBool(lua_State *L, int getFuncRef, auto save = luaScriptManager; luaScriptManager = lvglManager; int t = lua_gettop(L); - if (pcallFunc(L, getFuncRef, 1)) { - bool val = false; - if (lua_isboolean(L, -1)) - val = lua_toboolean(L, -1); - else - val = luaL_optinteger(L, -1, 0) != 0; - update(val); - lua_settop(L, t); + PROTECT_LUA() + { + if (pcallFunc(L, getFuncRef, 1)) { + bool val = false; + if (lua_isboolean(L, -1)) + val = lua_toboolean(L, -1); + else + val = luaL_optinteger(L, -1, 0) != 0; + update(val); + } else { + res = false; + } } else { - res = false; + lvglManager->luaShowError(); } - lvglManager = save; + UNPROTECT_LUA(); + lua_settop(L, t); + luaScriptManager = save; } return res; } @@ -215,14 +227,20 @@ bool LvglWidgetObjectBase::pcallUpdate1Int(lua_State *L, int getFuncRef, auto save = luaScriptManager; luaScriptManager = lvglManager; int t = lua_gettop(L); - if (pcallFunc(L, getFuncRef, 1)) { - int val = luaL_checkunsigned(L, -1); - update(val); - lua_settop(L, t); + PROTECT_LUA() + { + if (pcallFunc(L, getFuncRef, 1)) { + int val = luaL_checkunsigned(L, -1); + update(val); + } else { + res = false; + } } else { - res = false; + lvglManager->luaShowError(); } - lvglManager = save; + UNPROTECT_LUA(); + lua_settop(L, t); + luaScriptManager = save; } return res; } @@ -235,15 +253,21 @@ bool LvglWidgetObjectBase::pcallUpdate2Int(lua_State *L, int getFuncRef, auto save = luaScriptManager; luaScriptManager = lvglManager; int t = lua_gettop(L); - if (pcallFunc(L, getFuncRef, 2)) { - int v1 = luaL_checkunsigned(L, -2); - int v2 = luaL_checkunsigned(L, -1); - update(v1, v2); - lua_settop(L, t); + PROTECT_LUA() + { + if (pcallFunc(L, getFuncRef, 2)) { + int v1 = luaL_checkunsigned(L, -2); + int v2 = luaL_checkunsigned(L, -1); + update(v1, v2); + } else { + res = false; + } } else { - res = false; + lvglManager->luaShowError(); } - lvglManager = save; + UNPROTECT_LUA(); + lua_settop(L, t); + luaScriptManager = save; } return res; } @@ -265,14 +289,12 @@ int LvglWidgetObjectBase::pcallGetIntVal(lua_State *L, int getFuncRef) } else { lvglManager->luaShowError(); } - } - else - { + } else { lvglManager->luaShowError(); } UNPROTECT_LUA(); lua_settop(L, t); - lvglManager = save; + luaScriptManager = save; } return val; } @@ -294,14 +316,12 @@ int LvglWidgetObjectBase::pcallGetOptIntVal(lua_State *L, int getFuncRef, int de } else { lvglManager->luaShowError(); } - } - else - { + } else { lvglManager->luaShowError(); } UNPROTECT_LUA(); lua_settop(L, t); - lvglManager = save; + luaScriptManager = save; } return val; } @@ -317,14 +337,12 @@ void LvglWidgetObjectBase::pcallSetIntVal(lua_State *L, int setFuncRef, int val) if (!pcallFuncWithInt(L, setFuncRef, 0, val)) { lvglManager->luaShowError(); } - } - else - { + } else { lvglManager->luaShowError(); } UNPROTECT_LUA(); lua_settop(L, t); - lvglManager = save; + luaScriptManager = save; } } @@ -342,14 +360,12 @@ const char* LvglWidgetObjectBase::pcallGetStringVal(lua_State *L, int getFuncRef } else { lvglManager->luaShowError(); } - } - else - { + } else { lvglManager->luaShowError(); } UNPROTECT_LUA(); lua_settop(L, t); - lvglManager = save; + luaScriptManager = save; } return val; } @@ -365,14 +381,12 @@ void LvglWidgetObjectBase::pcallSetStringVal(lua_State *L, int setFuncRef, const if (!pcallFuncWithString(L, setFuncRef, 0, val)) { lvglManager->luaShowError(); } - } - else - { + } else { lvglManager->luaShowError(); } UNPROTECT_LUA(); lua_settop(L, t); - lvglManager = save; + luaScriptManager = save; } } @@ -471,6 +485,11 @@ void LvglWidgetObjectBase::clearChildRefs(lua_State *L) void LvglWidgetObjectBase::clearRefs(lua_State *L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, luaRef); + auto p = (LvglWidgetObjectBase **)luaL_testudata(L, -1, metatable); + if (p) *p = nullptr; + lua_pop(L, 1); + clearRef(L, luaRef); clearRef(L, color.function); clearRef(L, opacity.function); diff --git a/radio/src/lua/lua_lvgl_widget.h b/radio/src/lua/lua_lvgl_widget.h index 8fd49bd55..94150d2b2 100644 --- a/radio/src/lua/lua_lvgl_widget.h +++ b/radio/src/lua/lua_lvgl_widget.h @@ -86,7 +86,7 @@ class LvglWidgetObjectBase virtual Window *getWindow() const = 0; - static LvglWidgetObjectBase *checkLvgl(lua_State *L, int index); + static LvglWidgetObjectBase *checkLvgl(lua_State *L, int index, bool required = false); void clear(); diff --git a/radio/src/lua/lua_widget.cpp b/radio/src/lua/lua_widget.cpp index 086679435..5ccc30923 100644 --- a/radio/src/lua/lua_widget.cpp +++ b/radio/src/lua/lua_widget.cpp @@ -319,12 +319,12 @@ void LuaWidget::checkEvents() refresh(nullptr); if (!errorMessage) { if (!callRefs(lsWidgets)) { - setErrorMessage("callRefs()"); + setErrorMessage("function"); } } refreshInstructionsPercent = instructionsPercent; } else { - // TODO: error handling + setErrorMessage("function"); } luaScriptManager = save; UNPROTECT_LUA(); @@ -375,6 +375,7 @@ void LuaWidget::update() lua_setfield(lsWidgets, -2, option->name); } + auto save = luaScriptManager; luaScriptManager = this; if (lua_pcall(lsWidgets, 2, 0, 0) != 0) @@ -388,17 +389,17 @@ void LuaWidget::update() if (a.x2 >= 0 && a.x1 < LCD_W) { PROTECT_LUA() { if (!callRefs(lsWidgets)) { - setErrorMessage("callRefs()"); + setErrorMessage("function"); } } else { - // TODO: error handling + setErrorMessage("function"); } UNPROTECT_LUA(); } } } - luaScriptManager = nullptr; + luaScriptManager = save; } // Update table on top of Lua stack - set entry with name 'idx' to value 'val' @@ -459,12 +460,13 @@ void LuaWidget::onFullscreen(bool enable) void LuaWidget::setErrorMessage(const char* funcName) { + constexpr int err_len = 255; + const char* lua_err = lua_tostring(lsWidgets, -1); TRACE("Error in widget %s %s function: %s", factory->getName(), funcName, lua_err); TRACE("Widget disabled"); - size_t err_len = snprintf(NULL, 0, "ERROR in %s: %s", funcName, lua_err); errorMessage = (char*)malloc(err_len + 1); if (errorMessage) { @@ -473,6 +475,11 @@ void LuaWidget::setErrorMessage(const char* funcName) } } +void LuaWidget::luaShowError() +{ + setErrorMessage("widget"); +} + const char* LuaWidget::getErrorMessage() const { return errorMessage; } void LuaWidget::refresh(BitmapBuffer* dc) diff --git a/radio/src/lua/lua_widget.h b/radio/src/lua/lua_widget.h index 1432a9e61..8efb3f6d9 100644 --- a/radio/src/lua/lua_widget.h +++ b/radio/src/lua/lua_widget.h @@ -138,7 +138,7 @@ class LuaWidget : public Widget, public LuaScriptManager // Should rotary encoder events be enabled when full screen bool enableFullScreenRE() const override { return !useLvglLayout(); } - void luaShowError() override {} + void luaShowError() override; void pushOptionsTable();