From a64e9f89506106710022e0128180f76d21d5a6f7 Mon Sep 17 00:00:00 2001 From: Toni Spets Date: Fri, 15 May 2009 21:08:51 +0300 Subject: [PATCH] Lua scripting support, initial commit --- configure.ac.in | 19 ++++++ doc/config_settings.xml | 7 +++ doc/variables.xml | 20 ++++++ src/Makefile.am | 6 ++ src/conky.c | 65 ++++++++++++++++++++ src/conky.h | 4 ++ src/llua.c | 132 ++++++++++++++++++++++++++++++++++++++++ src/llua.h | 14 +++++ src/text_object.h | 4 ++ 9 files changed, 271 insertions(+) create mode 100644 src/llua.c create mode 100644 src/llua.h diff --git a/configure.ac.in b/configure.ac.in index 2deabd9f..2398c103 100644 --- a/configure.ac.in +++ b/configure.ac.in @@ -324,6 +324,24 @@ if test x$want_rss = xyes; then AC_DEFINE(RSS, 1, [Define if you want rss support]) fi +dnl +dnl Lua +dnl + +AC_ARG_ENABLE([lua], + AC_HELP_STRING([--enable-lua], [enable if you want Lua scripting support @<:@default=no@:>@]), + [want_lua="$enableval"], [want_lua=no]) +# +AM_CONDITIONAL(BUILD_LUA, test x$want_lua = xyes) +if test x$want_lua = xyes; then + PKG_CHECK_MODULES(LUA, lua >= 5.1, [ ],[ + PKG_CHECK_MODULES(LUA51, lua5.1 >= 5.1, [ ]) + ]) + CFLAGS="$CFLAGS $LUA_CFLAGS $LUA51_CFLAGS" + LIBS="$LIBS $LUA_LIBS $LUA51_LIBS" + AC_DEFINE(HAVE_LUA, 1, [Define if you want Lua scripting support]) +fi + dnl dnl Wireless extensions dnl @@ -781,6 +799,7 @@ $PACKAGE $VERSION configured successfully: hddtemp: $want_hddtemp portmon: $want_portmon RSS: $want_rss + Lua: $want_lua wireless: $want_wlan IBM: $want_ibm nvidia: $want_nvidia diff --git a/doc/config_settings.xml b/doc/config_settings.xml index 7a2f80de..6818d83f 100644 --- a/doc/config_settings.xml +++ b/doc/config_settings.xml @@ -513,6 +513,13 @@ + + + + Loads the Lua scripts separated by spaces. + + + diff --git a/doc/variables.xml b/doc/variables.xml index c2162935..6b49936b 100644 --- a/doc/variables.xml +++ b/doc/variables.xml @@ -2341,6 +2341,26 @@ + + + + + + + Executes a Lua function with given parameters and prints the result value. + + + + + + + + + + Executes a Lua function with given parameters and prints a bar. Expects result value to be an integer between 0 and 100. + + + diff --git a/src/Makefile.am b/src/Makefile.am index 61f202df..689ea800 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -107,6 +107,10 @@ if BUILD_RSS rss = rss.c prss.c prss.h endif +if BUILD_LUA +lua = llua.c llua.h +endif + if BUILD_NVIDIA nvidia = nvidia.c nvidia.h endif @@ -141,6 +145,7 @@ conky_SOURCES = \ $(port_monitors) \ $(eve) \ $(rss) \ + $(lua) \ $(solaris) \ timed_thread.c \ timed_thread.h \ @@ -189,6 +194,7 @@ EXTRA_DIST = \ libtcp-portmon.c \ libtcp-portmon.h \ rss.h \ + llua.h \ mail.h \ mixer.h \ moc.h \ diff --git a/src/conky.c b/src/conky.c index e8cc412d..b81b7d88 100644 --- a/src/conky.c +++ b/src/conky.c @@ -196,6 +196,9 @@ static void print_version(void) #ifdef RSS " * RSS\n" #endif /* RSS */ +#ifdef HAVE_LUA + " * Lua\n" +#endif /* HAVE_LUA */ #ifdef HAVE_IWLIB " * wireless\n" #endif /* HAVE_IWLIB */ @@ -848,6 +851,14 @@ static void free_text_objects(struct text_object *root) free(data.rss.uri); free(data.rss.action); break; +#endif +#ifdef HAVE_LUA + case OBJ_lua: + llua_close(); + break; + case OBJ_lua_bar: + llua_close(); + break; #endif case OBJ_pre_exec: break; @@ -2568,6 +2579,28 @@ static struct text_object *construct_text_object(const char *s, "[act_par] [spaces in front]"); } #endif +#ifdef HAVE_LUA + END OBJ(lua, 0) + if(arg) { + obj->data.s = strndup(arg, text_buffer_size); + } else { + CRIT_ERR("lua needs arguments: [function parameters]"); + } + +#ifdef X11 + END OBJ(lua_bar, 0) + if(arg) { + arg = scan_bar(arg, &obj->a, &obj->b); + if(arg) { + obj->data.s = strndup(arg, text_buffer_size); + } else { + CRIT_ERR("lua_bar needs arguments: , [function parameters]"); + } + } else { + CRIT_ERR("lua_bar needs arguments: , [function parameters]"); + } +#endif +#endif #ifdef HDDTEMP END OBJ(hddtemp, 0) if (scan_hddtemp(arg, &obj->data.hddtemp.dev, @@ -4147,6 +4180,24 @@ static void generate_text_internal(char *p, int p_max_size, } } #endif +#ifdef HAVE_LUA + OBJ(lua) { + char *str = llua_getstring(obj->data.s); + if(str) { + snprintf(p, p_max_size, "%s", str); + free(str); + } + } + +#ifdef X11 + OBJ(lua_bar) { + int per; + if(llua_getpercent(strdup(obj->data.s), &per)) { + new_bar(p, obj->a, obj->b, (per/100.0 * 255)); + } + } +#endif +#endif #ifdef HDDTEMP OBJ(hddtemp) { char *endptr, unit; @@ -7653,6 +7704,20 @@ static void load_config_file(const char *f) CONF_ERR; } } +#ifdef HAVE_LUA + CONF("lua_load") { + llua_init(); + if(value) { + char *ptr = strtok(value, " "); + while(ptr) { + llua_load(ptr); + ptr = strtok(NULL, " "); + } + } else { + CONF_ERR; + } + } +#endif CONF("color0"){} CONF("color1"){} diff --git a/src/conky.h b/src/conky.h index b12952ec..a8206444 100644 --- a/src/conky.h +++ b/src/conky.h @@ -90,6 +90,10 @@ char *strndup(const char *s, size_t n); #include "rss.h" #endif +#ifdef HAVE_LUA +#include "llua.h" +#endif + #ifdef TCP_PORT_MONITOR #include "tcp-portmon.h" #endif diff --git a/src/llua.c b/src/llua.c new file mode 100644 index 00000000..1d9070c2 --- /dev/null +++ b/src/llua.c @@ -0,0 +1,132 @@ +/* Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2007 Toni Spets + * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * 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 3 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 . + * + */ + +#include "conky.h" + +lua_State *lua_L = NULL; + +void llua_init() +{ + if(lua_L) return; + lua_L = lua_open(); + luaL_openlibs(lua_L); +} + +void llua_load(const char *script) +{ + int error; + error = luaL_loadfile(lua_L, script); + if(error) { + fprintf(stderr, "llua_load: %s\n", lua_tostring(lua_L, -1)); + lua_pop(lua_L, 1); + } else { + lua_pcall(lua_L, 0, 0, 0); + } +} + +char *llua_getstring(const char *args) +{ + char *ret = NULL; + char *tmp = strdup(args); + char func[64]; + int parcount = 0; + + if(!lua_L) return NULL; + + char *ptr = strtok(tmp, " "); + if(!ptr) return NULL; /* function name missing */ + snprintf(func, 64, "conky_%s", ptr); + + lua_getglobal(lua_L, func); + + ptr = strtok(NULL, " "); + while(ptr) { + lua_pushstring(lua_L, ptr); + ptr = strtok(NULL, " "); + parcount++; + } + + if(lua_pcall(lua_L, parcount, 1, 0) != 0) { + fprintf(stderr, "llua: function %s execution failed: %s\n", func, lua_tostring(lua_L, -1)); + lua_pop(lua_L, -1); + } else { + if(!lua_isstring(lua_L, -1)) { + fprintf(stderr, "llua: function %s didn't return a string, result discarded\n", func); + } else { + ret = strdup((char *)lua_tostring(lua_L, -1)); + lua_pop(lua_L, 1); + } + } + + free(tmp); + + return ret; +} + +int llua_getpercent(const char *args, int *per) +{ + char func[64]; + char *tmp = strdup(args); + int parcount = 0; + + if(!lua_L) return 0; + + char *ptr = strtok(tmp, " "); + if(!ptr) return 0; /* function name missing */ + snprintf(func, 64, "conky_%s", ptr); + + lua_getglobal(lua_L, func); + + ptr = strtok(NULL, " "); + while(ptr) { + lua_pushstring(lua_L, ptr); + ptr = strtok(NULL, " "); + parcount++; + } + free(tmp); + + if(lua_pcall(lua_L, parcount, 1, 0) != 0) { + fprintf(stderr, "llua: function %s execution failed: %s\n", func, lua_tostring(lua_L, -1)); + lua_pop(lua_L, -1); + } else { + if(!lua_isnumber(lua_L, -1)) { + fprintf(stderr, "llua: function %s didn't return a number (percent), result discarded\n", func); + } else { + *per = lua_tonumber(lua_L, -1); + lua_pop(lua_L, 1); + return 1; + } + } + return 0; +} + +void llua_close() +{ + if(!lua_L) return; + lua_close(lua_L); + lua_L = NULL; +} diff --git a/src/llua.h b/src/llua.h new file mode 100644 index 00000000..596f2b4d --- /dev/null +++ b/src/llua.h @@ -0,0 +1,14 @@ +#ifndef LUA_H_ +#define LUA_H_ + +#include +#include +#include + +void llua_init(); +void llua_load(const char *script); +char *llua_getstring(const char *args); +int llua_getpercent(const char *args, int *per); +void llua_close(); + +#endif /* LUA_H_*/ diff --git a/src/text_object.h b/src/text_object.h index fe915a28..a4f13bcb 100644 --- a/src/text_object.h +++ b/src/text_object.h @@ -380,6 +380,10 @@ enum text_object_type { #ifdef RSS OBJ_rss, #endif +#ifdef HAVE_LUA + OBJ_lua, + OBJ_lua_bar, +#endif #ifdef TCP_PORT_MONITOR OBJ_tcp_portmon, #endif