diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 4b7a7457d..31172013f 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -202,16 +202,55 @@ if(NOT LUA STREQUAL NO) if(LUA STREQUAL YES) add_definitions(-DLUA_MODEL_SCRIPTS) endif() - set(SRC ${SRC} lua/interface.cpp lua/api_general.cpp lua/api_model.cpp) + + # TODO: LUA CMAKE + set(SRC ${SRC} + lua/interface.cpp + lua/api_general.cpp + lua/api_model.cpp + lua/api_filesystem.cpp + ) + if(GUI_DIR STREQUAL colorlcd) set(SRC ${SRC} lua/api_colorlcd.cpp lua/widgets.cpp) else() set(SRC ${SRC} lua/api_stdlcd.cpp) endif() - set(LUA_SRC lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c - lstate.c lstring.c ltable.c lrotable.c ltm.c lundump.c lvm.c lzio.c linit.c - lbaselib.c lmathlib.c lbitlib.c loadlib.c lauxlib.c ltablib.c lcorolib.c liolib.c lstrlib.c - ) + + set(LUA_SRC + lapi.c + lcode.c + lctype.c + ldebug.c + ldo.c + ldump.c + lfunc.c + lgc.c + llex.c + lmem.c + lobject.c + lopcodes.c + lparser.c + lstate.c + lstring.c + ltable.c + lrotable.c + ltm.c + lundump.c + lvm.c + lzio.c + linit.c + lbaselib.c + lmathlib.c + lbitlib.c + loadlib.c + lauxlib.c + ltablib.c + lcorolib.c + liolib.c + lstrlib.c + ) + foreach(FILE ${LUA_SRC}) set(SRC ${SRC} ${LUA_DIR}/${FILE}) endforeach() diff --git a/radio/src/lua/api_colorlcd.cpp b/radio/src/lua/api_colorlcd.cpp index 7be6b70d0..2f04fe0de 100644 --- a/radio/src/lua/api_colorlcd.cpp +++ b/radio/src/lua/api_colorlcd.cpp @@ -21,7 +21,6 @@ #include #include #include "opentx.h" -#include "lua_api.h" #include "libopenui.h" #include "api_colorlcd.h" diff --git a/radio/src/lua/api_filesystem.cpp b/radio/src/lua/api_filesystem.cpp new file mode 100644 index 000000000..39f2b1bf6 --- /dev/null +++ b/radio/src/lua/api_filesystem.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + + +#include +#include "lua_api.h" + +#include "api_filesystem.h" + +// garbage collector for luaDir +static int dir_gc(lua_State* L) +{ + DIR* dir = (DIR*)lua_touserdata(L, 1); + if (dir) f_closedir(dir); + return 0; +} + +void registerDirIter(lua_State* L) +{ + luaL_newmetatable(L, DIR_METATABLE); + + /* set the garbage colector field */ + lua_pushstring(L, "__gc"); + lua_pushcfunction(L, dir_gc); + lua_settable(L, -3); + + lua_pop(L, 1); +} + +static int dir_iter(lua_State* L) +{ + DIR* dir = (DIR*)lua_touserdata(L, lua_upvalueindex(1)); + + FILINFO info; + FRESULT res = f_readdir(dir, &info); + if (res != FR_OK || info.fname[0] == 0) { /* Break on error or end of dir */ + return 0; + } + + lua_pushstring(L, info.fname); + return 1; +} + +/*luadoc +@function dir(directory) + + Return an iterator listing all the files and directories name in a directory + +@param directory (string) Working directory + +@status current Introduced in ???? + +### Example + +```lua + for fname in dir(".") do + print(fname) + end + +*/ +int luaDir(lua_State* L) +{ + const char* path = luaL_optstring(L, 1, nullptr); + DIR* dir = (DIR*)lua_newuserdata(L, sizeof(DIR)); + + luaL_getmetatable(L, DIR_METATABLE); + lua_setmetatable(L, -2); + + FRESULT res = f_opendir(dir, path); + if (res != FR_OK) { + printf("luaDir cannot open %s\n", path); + } + + lua_pushcclosure(L, dir_iter, 1); + return 1; +} + +/*luadoc +@function fstat(path) + + Checks the existence of file or directory. + If not exist, return nil. + If exist, return the object information. + +@param path (string) path to the object + +@retval table object info, table elements: +* 'size' (number) file size +* 'attrib' (number) file attribute flags +* 'time' (table) table with last time modified date and times, table elements: + * `year` (number) year + * `mon` (number) month + * `day` (number) day of month + * `hour` (number) hours + * `hour12` (number) hours in US format + * `min` (number) minutes + * `sec` (number) seconds + * `suffix` (text) am or pm + +### Example + +```lua + info = fstat("radio") + if info ~= nil then + if (info.attrib == AM_DIR) then + print("is a directory") + end + + size = info.size + time = info.time + end + +@status current Introduced in ???? + +*/ +int luaFstat(lua_State* L) +{ + const char * path = luaL_optstring(L, 1, nullptr); + + FRESULT res; + FILINFO info; + + res = f_stat(path, &info); + if (res != FR_OK) { + printf("luaFstat cannot open %s\n", path); + return 0; + } + + lua_newtable(L); + lua_pushtableinteger(L, "size", info.fsize); + lua_pushtableinteger(L, "attrib", info.fattrib); + + uint32_t year = (info.fdate >> 9) + 1980; + uint32_t month = info.fdate >> 5 & 15; + uint32_t day = info.fdate & 31; + uint32_t hour = info.ftime >> 11; + uint32_t mn = info.ftime >> 5 & 63; + uint32_t sec = (info.ftime & 31) * 2; + + lua_pushstring(L, "time"); + luaPushDateTime(L, year, month, day, hour, mn, sec); + lua_settable(L, -3); + + return 1; +} \ No newline at end of file diff --git a/radio/src/lua/api_filesystem.h b/radio/src/lua/api_filesystem.h new file mode 100644 index 000000000..8e7751dce --- /dev/null +++ b/radio/src/lua/api_filesystem.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +#define DIR_METATABLE "directory metatable" + +void registerDirIter(lua_State* L); +int luaDir(lua_State* L); +int luaFstat(lua_State* L); \ No newline at end of file diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 3b20c366b..e76e37326 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -23,6 +23,7 @@ #include "opentx.h" #include "stamp.h" #include "lua_api.h" +#include "api_filesystem.h" #include "telemetry/frsky.h" #include "telemetry/multi.h" @@ -165,7 +166,7 @@ static int luaGetTime(lua_State * L) return 1; } -static void luaPushDateTime(lua_State * L, uint32_t year, uint32_t mon, uint32_t day, +void luaPushDateTime(lua_State * L, uint32_t year, uint32_t mon, uint32_t day, uint32_t hour, uint32_t min, uint32_t sec) { uint32_t hour12 = hour; @@ -1816,6 +1817,8 @@ const luaL_Reg opentxLib[] = { { "defaultChannel", luaDefaultChannel }, { "getRSSI", luaGetRSSI }, { "killEvents", luaKillEvents }, + { "dir", luaDir }, + { "fstat", luaFstat }, { "chdir", luaChdir }, { "loadScript", luaLoadScript }, { "getUsage", luaGetUsage }, @@ -2175,5 +2178,11 @@ const luaR_value_entry opentxConstants[] = { {"UNIT_BITFIELD", UNIT_BITFIELD}, {"UNIT_TEXT", UNIT_TEXT}, + {"AM_RDO", AM_RDO}, + {"AM_HID", AM_HID}, + {"AM_SYS", AM_SYS}, + {"AM_DIR", AM_DIR}, + {"AM_ARC", AM_ARC}, + { nullptr, 0 } /* sentinel */ }; diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index 1c53ca4bd..59a273e98 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -29,6 +29,7 @@ #include "sdcard.h" #if defined(LIBOPENUI) + #include "api_filesystem.h" #include "api_colorlcd.h" #include "libopenui.h" #else @@ -257,6 +258,8 @@ void luaClose(lua_State ** L) void luaRegisterLibraries(lua_State * L) { luaL_openlibs(L); + registerDirIter(L); + #if defined(COLORLCD) registerBitmapClass(L); #endif diff --git a/radio/src/lua/lua_api.h b/radio/src/lua/lua_api.h index ca0d9c294..8b663c6ab 100644 --- a/radio/src/lua/lua_api.h +++ b/radio/src/lua/lua_api.h @@ -23,6 +23,9 @@ #if defined(LUA) +// prevent C++ code to be included from lua.h +#include "rtos.h" + extern "C" { #include #include @@ -31,6 +34,9 @@ extern "C" { #include } +#include "dataconstants.h" +#include "opentx_types.h" + #ifndef LUA_SCRIPT_LOAD_MODE // Can force loading of binary (.luac) or plain-text (.lua) versions of scripts specifically, and control // compilation options. See interface.cpp:luaLoadScriptFileToState() parameter description for details. @@ -209,6 +215,8 @@ void luaRegisterLibraries(lua_State * L); void registerBitmapClass(lua_State * L); void luaSetInstructionsLimit(lua_State* L, int count); int luaLoadScriptFileToState(lua_State * L, const char * filename, const char * mode); +void luaPushDateTime(lua_State * L, uint32_t year, uint32_t mon, uint32_t day, + uint32_t hour, uint32_t min, uint32_t sec); // Unregister LUA widget factories void luaUnregisterWidgets();