summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/MirLua/src/m_schedule.cpp563
-rw-r--r--plugins/MirLua/src/m_schedule.h9
-rw-r--r--plugins/MirLua/src/mlua.cpp10
-rw-r--r--plugins/MirLua/src/mlua_metatable.h3
-rw-r--r--plugins/MirLua/src/mlua_module_loader.cpp1
-rw-r--r--plugins/MirLua/src/stdafx.h7
6 files changed, 580 insertions, 13 deletions
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<ScheduleTask> 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(&timestamp);
+ 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(&timestamp);
+ 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(&timestamp);
+ 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<void> CMLua::Hooks(1, PtrKeySortT);
-//LIST<void> CMLua::Events(1, PtrKeySortT);
-//LIST<void> CMLua::Services(1, PtrKeySortT);
LIST<void> CMLua::HookRefs(1, HandleKeySortT);
LIST<void> 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 <map>
-#include <string>
-
#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 <malloc.h>
#include <time.h>
+#include <map>
+#include <string>
+
#include <newpluginapi.h>
#include <m_core.h>
#include <m_utils.h>
@@ -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 <typeinfo>
-
#endif //_COMMON_H_