From 6512084bf5cb6f40060cb0c9d8cb518b7417e373 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sun, 6 Dec 2015 19:27:52 +0000 Subject: MirLua: added schedule module git-svn-id: http://svn.miranda-ng.org/main/trunk@15821 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MirLua/src/m_schedule.cpp | 563 ++++++++++++++++++++++++++++++ plugins/MirLua/src/m_schedule.h | 9 + plugins/MirLua/src/mlua.cpp | 10 +- plugins/MirLua/src/mlua_metatable.h | 3 - plugins/MirLua/src/mlua_module_loader.cpp | 1 + plugins/MirLua/src/stdafx.h | 7 +- 6 files changed, 580 insertions(+), 13 deletions(-) create mode 100644 plugins/MirLua/src/m_schedule.cpp create mode 100644 plugins/MirLua/src/m_schedule.h (limited to 'plugins') diff --git a/plugins/MirLua/src/m_schedule.cpp b/plugins/MirLua/src/m_schedule.cpp new file mode 100644 index 0000000000..8d2330f626 --- /dev/null +++ b/plugins/MirLua/src/m_schedule.cpp @@ -0,0 +1,563 @@ +#include "stdafx.h" + +static mir_cs threadLock; +static HANDLE hScheduleEvent = NULL; +static HANDLE hScheduleThread = NULL; + +struct ScheduleTask +{ + time_t startTime; + time_t endTime; + time_t interval; + + lua_State *L; + lua_State *T; + int threadRef; + int callbackRef; +}; + +static int TaskCompare(const ScheduleTask *p1, const ScheduleTask *p2) +{ + return p1->startTime - p2->startTime; +} + +static LIST tasks(1, TaskCompare); + +void DestroyScheduleTask(ScheduleTask *task) +{ + luaL_unref(task->L, LUA_REGISTRYINDEX, task->threadRef); + delete task; +} + +void ScheduleThread(void*) +{ + time_t waitTime = INFINITE; + + while (true) + { +wait: WaitForSingleObject(hScheduleEvent, waitTime); + + while (ScheduleTask *task = tasks[0]) + { + mir_cslock lock(threadLock); + + time_t timestamp = time(NULL); + if (task->startTime > timestamp) + { + waitTime = (task->startTime - timestamp - 1) * 1000; + goto wait; + } + + tasks.remove(task); + + if (task->endTime > 0 && task->endTime < timestamp) + { + DestroyScheduleTask(task); + continue; + } + + lua_rawgeti(task->T, LUA_REGISTRYINDEX, task->callbackRef); + if (lua_pcall(task->T, 0, 2, 0)) + CallService(MS_NETLIB_LOG, (WPARAM)hNetlib, (LPARAM)lua_tostring(task->T, -1)); + + if (task->interval == 0) + { + DestroyScheduleTask(task); + continue; + } + + task->startTime += task->interval; + tasks.insert(task); + } + + waitTime = INFINITE; + } +} + +void KillModuleScheduleTasks() +{ + mir_cslock lock(threadLock); + + while (ScheduleTask *task = tasks[0]) + { + tasks.remove(task); + DestroyScheduleTask(task); + } +} + +/***********************************************/ + +enum DayOfWeek +{ + None = -1, + Sunday = 0, + Monday = 1, + Tuesday = 2, + Wednesday = 3, + Thursday = 4, + Friday = 5, + Saturday = 6 +}; + +static int lua__Second(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 1); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, time(NULL)); + lua_setfield(L, -2, "Timestamp"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Seconds(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushliteral(L, "Interval"); + lua_gettable(L, -2); + int seconds = luaL_optinteger(L, -1, 1); + lua_pop(L, 1); + lua_pushinteger(L, seconds); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Minute(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Minutes(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushliteral(L, "Interval"); + lua_gettable(L, -2); + int interval = luaL_optinteger(L, -1, 1); + lua_pop(L, 1); + lua_pushinteger(L, interval * 60); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Hour(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Hours(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushliteral(L, "Interval"); + lua_gettable(L, -2); + int interval = luaL_optinteger(L, -1, 1); + lua_pop(L, 1); + lua_pushinteger(L, interval * 60 * 60); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Day(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Days(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushliteral(L, "Interval"); + lua_gettable(L, -2); + int interval = luaL_optinteger(L, -1, 1); + lua_pop(L, 1); + lua_pushinteger(L, interval * 60 * 60 * 24); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Week(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Weeks(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushliteral(L, "Interval"); + lua_gettable(L, -2); + int interval = luaL_optinteger(L, -1, 1); + lua_pop(L, 1); + lua_pushinteger(L, interval * 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, DayOfWeek::None); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Monday(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, Monday); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Tuesday(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, Tuesday); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Wednesday(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, Wednesday); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Thursday(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, Thursday); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Friday(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, Friday); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Saturday(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, Saturday); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__Sunday(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + lua_pushinteger(L, 60 * 60 * 24 * 7); + lua_setfield(L, -2, "Interval"); + lua_pushinteger(L, Sunday); + lua_setfield(L, -2, "DayOfWeek"); + + return 1; +} + +static int lua__From(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + time_t startTime, timestamp = time(NULL); + switch (lua_type(L, 2)) + { + case LUA_TNUMBER: + startTime = luaL_optinteger(L, 2, timestamp); + break; + + case LUA_TSTRING: + { + const char *strtime = luaL_optstring(L, 2, "00:00:00"); + + int hour = 0, min = 0, sec = 0; + sscanf_s(strtime, "%02d:%02d:%02d", &hour, &min, &sec); + struct tm *ti = localtime(×tamp); + ti->tm_hour = hour; + ti->tm_min = min; + ti->tm_sec = sec; + startTime = mktime(ti); + break; + } + + default: + startTime = timestamp; + break; + } + + if (startTime < timestamp) + { + lua_pushliteral(L, "Interval"); + lua_gettable(L, 1); + int interval = luaL_optinteger(L, -1, 1); + lua_pop(L, 1); + startTime += (((timestamp - startTime) / interval) + 1) * interval; + } + + lua_pushvalue(L, 1); + lua_pushinteger(L, startTime); + lua_setfield(L, -2, "StartTime"); + + return 1; +} + +static int lua__Untill(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + + time_t endTime = 0; + switch (lua_type(L, 2)) + { + case LUA_TNUMBER: + endTime = luaL_optinteger(L, 2, 0); + break; + + case LUA_TSTRING: + { + const char *strtime = luaL_optstring(L, 2, "00:00:00"); + + int hour = 0, min = 0, sec = 0; + sscanf_s(strtime, "%02d:%02d:%02d", &hour, &min, &sec); + time_t timestamp = time(NULL); + struct tm *ti = localtime(×tamp); + ti->tm_hour = hour; + ti->tm_min = min; + ti->tm_sec = sec; + endTime = mktime(ti); + break; + } + } + + lua_pushvalue(L, 1); + lua_pushinteger(L, endTime); + lua_setfield(L, -2, "EndTime"); + + return 1; +} + +static int lua__Do(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_pushliteral(L, "Interval"); + lua_gettable(L, 1); + int interval = luaL_optinteger(L, -1, 0); + lua_pop(L, 1); + + time_t timestamp = time(NULL); + + lua_pushliteral(L, "StartTime"); + lua_gettable(L, 1); + time_t startTime = luaL_optinteger(L, -1, timestamp); + lua_pop(L, 1); + + if (startTime < timestamp && interval == 0) + return 0; + + lua_pushliteral(L, "DayOfWeek"); + lua_gettable(L, 1); + DayOfWeek dayOfWeek = (DayOfWeek)luaL_optinteger(L, -1, DayOfWeek::None); + lua_pop(L, 1); + + if (dayOfWeek > DayOfWeek::None && dayOfWeek <= DayOfWeek::Saturday) + { + struct tm *ti = localtime(&startTime); + ti->tm_mday += abs((int)dayOfWeek - ti->tm_wday); + startTime = mktime(ti); + } + + lua_pushliteral(L, "EndTime"); + lua_gettable(L, 1); + time_t endTime = luaL_optinteger(L, -1, 0); + lua_pop(L, 1); + + if (endTime > 0 && endTime < timestamp) + return 0; + + ScheduleTask *task = new ScheduleTask(); + task->startTime = startTime; + task->endTime = endTime; + task->interval = interval; + task->L = L; + lua_pushvalue(L, 2); + task->callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); + task->T = lua_newthread(L); + task->threadRef = luaL_ref(L, LUA_REGISTRYINDEX); + { + mir_cslock lock(threadLock); + tasks.insert(task); + } + SetEvent(hScheduleEvent); + + return 0; +} + +static const luaL_Reg schedule[] = +{ + { "Second", lua__Second }, + { "Seconds", lua__Seconds }, + { "Minute", lua__Minute }, + { "Minutes", lua__Minutes }, + { "Hour", lua__Hour }, + { "Hours", lua__Hours }, + { "Day", lua__Day }, + { "Days", lua__Days }, + { "Week", lua__Week }, + { "Weeks", lua__Weeks }, + { "Monday", lua__Week }, + { "Tuesday", lua__Tuesday }, + { "Wednesday", lua__Wednesday }, + { "Thursday", lua__Thursday }, + { "Friday", lua__Friday }, + { "Saturday", lua__Saturday }, + { "Sunday", lua__Sunday }, + { "From", lua__From }, + { "Untill", lua__Untill }, + { "Do", lua__Do }, + + { NULL, NULL } +}; + +/***********************************************/ + +static int lua__At(lua_State *L) +{ + time_t startTime, timestamp = time(NULL); + switch (lua_type(L, 1)) + { + case LUA_TNUMBER: + startTime = luaL_optinteger(L, 1, timestamp); + break; + + case LUA_TSTRING: + { + const char *strtime = luaL_optstring(L, 1, "00:00:00"); + + int hour = 0, min = 0, sec = 0; + sscanf_s(strtime, "%02d:%02d:%02d", &hour, &min, &sec); + struct tm *ti = localtime(×tamp); + ti->tm_hour = hour; + ti->tm_min = min; + ti->tm_sec = sec; + startTime = mktime(ti); + break; + } + + default: + startTime = timestamp; + break; + } + + lua_newtable(L); + lua_pushcclosure(L, lua__Untill, 0); + lua_setfield(L, -2, "Untill"); + lua_pushcclosure(L, lua__Do, 0); + lua_setfield(L, -2, "Do"); + lua_pushinteger(L, startTime); + lua_setfield(L, -2, "StartTime"); + + return 1; +} + +static int lua__Every(lua_State *L) +{ + int interval = luaL_optinteger(L, 1, 0); + + luaL_newlib(L, schedule); + lua_pushinteger(L, interval); + lua_setfield(L, -2, "Interval"); + + return 1; +} + +static const luaL_Reg scheduleApi[] = +{ + { "At", lua__At }, + { "Every", lua__Every }, + + { NULL, NULL } +}; + +LUAMOD_API int luaopen_m_schedule(lua_State *L) +{ + luaL_newlib(L, scheduleApi); + + if (hScheduleEvent == NULL) + hScheduleEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if (hScheduleThread == NULL) + hScheduleThread = mir_forkthread(ScheduleThread); + + return 1; +} diff --git a/plugins/MirLua/src/m_schedule.h b/plugins/MirLua/src/m_schedule.h new file mode 100644 index 0000000000..48874dd126 --- /dev/null +++ b/plugins/MirLua/src/m_schedule.h @@ -0,0 +1,9 @@ +#ifndef _LUA_M_SCHEDULE_H_ +#define _LUA_M_SCHEDULE_H_ + +#define MLUA_SCHEDULE "m_schedule" +LUAMOD_API int (luaopen_m_schedule)(lua_State *L); + +void KillModuleScheduleTasks(); + +#endif //_LUA_M_SCHEDULE_H_ \ No newline at end of file diff --git a/plugins/MirLua/src/mlua.cpp b/plugins/MirLua/src/mlua.cpp index 5a17246a5f..de7690356e 100644 --- a/plugins/MirLua/src/mlua.cpp +++ b/plugins/MirLua/src/mlua.cpp @@ -1,8 +1,5 @@ #include "stdafx.h" -//LIST CMLua::Hooks(1, PtrKeySortT); -//LIST CMLua::Events(1, PtrKeySortT); -//LIST CMLua::Services(1, PtrKeySortT); LIST CMLua::HookRefs(1, HandleKeySortT); LIST CMLua::ServiceRefs(1, HandleKeySortT); @@ -65,6 +62,7 @@ void CMLua::Unload() delete script; } + ::KillModuleScheduleTasks(); ::KillModuleMBButtons(); ::KillModuleTTBButton(); @@ -73,12 +71,8 @@ void CMLua::Unload() ::KillModuleHotkeys(hScriptsLangpack); ::KillObjectEventHooks(L); ::KillObjectServices(L); - //KillModuleSubclassing - //CMLua::KillLuaRefs(); - - if (L) - lua_close(L); + lua_close(L); } void CMLua::KillLuaRefs() diff --git a/plugins/MirLua/src/mlua_metatable.h b/plugins/MirLua/src/mlua_metatable.h index b0d31cf707..f2143d5f27 100644 --- a/plugins/MirLua/src/mlua_metatable.h +++ b/plugins/MirLua/src/mlua_metatable.h @@ -1,9 +1,6 @@ #ifndef _LUA_METATABLE_H_ #define _LUA_METATABLE_H_ -#include -#include - #define LUA_TINTEGER LUA_NUMTAGS + 1 #define LUA_TSTRINGA LUA_NUMTAGS + 2 #define LUA_TSTRINGW LUA_NUMTAGS + 3 diff --git a/plugins/MirLua/src/mlua_module_loader.cpp b/plugins/MirLua/src/mlua_module_loader.cpp index a236a76691..a40f24b7ab 100644 --- a/plugins/MirLua/src/mlua_module_loader.cpp +++ b/plugins/MirLua/src/mlua_module_loader.cpp @@ -16,6 +16,7 @@ void CLuaModuleLoader::LoadModules() { // regirter delay loading of miranda modules PreloadModule(MLUA_CORE, luaopen_m_core); + PreloadModule(MLUA_SCHEDULE, luaopen_m_schedule); PreloadModule(MLUA_CLIST, luaopen_m_clist); PreloadModule(MLUA_DATABASE, luaopen_m_database); PreloadModule(MLUA_ICOLIB, luaopen_m_icolib); diff --git a/plugins/MirLua/src/stdafx.h b/plugins/MirLua/src/stdafx.h index 0929db0d56..1c1677a2bd 100644 --- a/plugins/MirLua/src/stdafx.h +++ b/plugins/MirLua/src/stdafx.h @@ -6,6 +6,9 @@ #include #include +#include +#include + #include #include #include @@ -69,6 +72,8 @@ extern HANDLE hNetlib; #define MLUA_CORE "m_core" LUAMOD_API int (luaopen_m_core)(lua_State *L); +#include "m_schedule.h" + #define MLUA_CLIST "m_clist" LUAMOD_API int (luaopen_m_clist)(lua_State *L); @@ -121,6 +126,4 @@ void ShowNotification(const char *caption, const char *message, int flags, MCONT void ObsoleteMethod(lua_State *L, const char *message); -#include - #endif //_COMMON_H_ -- cgit v1.2.3