Lua и расписание

Напомню, что в предыдущих частях мы построили приложение, способное отсчитывать временные интервалы и оповещать пользователя в нужный момент. Ясно, что параметров, на которые пользователь хотел бы влиять, довольно много. Это значки и текст в оповещении, распределение времени, учет повторяющихся временных блоков и т.д.. Кроме того, хотелось бы иметь возможность вести статистику и менять формат её ведения при желании. В таких условиях целесообразно возложить задачу настройки и построения сценария работы на внешний скрипт. Для этого будем использовать lua.

О Lua

Так как наше приложение написано на C++, а библиотека lua рассчитана на работу с языком C, следует скачать и добавить в проект файл luawrapper.hpp. Делается это для того, чтобы создать прототипы функций и структур приложения для скриптов lua.

Makefile

TARGET = mySchedule
CC = g++
LIBS = -lnotify -llua5.1
CFLAGS = -std=c++11 `pkg-config gtk+-2.0 --cflags`
OBJ = main.o
app: ${OBJ}
	${CC} ${CFLAGS} ${OBJ} ${LIBS} -o ${TARGET}
main.o: main.cpp
	${CC} ${CFLAGS} -c main.cpp 
clean:
	rm -rf *.o ${TARGET}

По сравнению с предыдущей версией makefile-а, добавилась запись -llua5.1. Версия данной библиотеки может отличаться, но во многих репозиториях она присутствует. В переменной TARGET можно указать любое имя, которое вы хотите дать приложению.

Расписание и временные промежутки

Отрезок времени можно описать по разному. В системах на подобие pomodoro не столь важно — когда мы начали работу и когда закончили, а сколько времени было потрачено. Поэтому главной характеристикой временного промежутка будет его длительность. Также важно каким-то образом реагировать на окончание временного промежутка и его начало. Кроме того, полезно дать промежутку определенное имя («Работа», «Перерыв», «Большой перерыв» и т.д.). Собственно, на этом описание можно завершить.

struct TimeStamp {
	char* name;
	char* onStart;
	char* onEnd;
	double duration;
};

Здесь duration — длительность в секундах (доли секунд тоже учитываются, поэтому тип — double). name — имя интервала. onStart и onEnd — имена функций в скрипте lua, которые будут вызваны в начале и конце временного промежутка соответственно.

Мы предполагаем, что каждый интервал является частью некоторой схемы или расписания. «Работа» — 25 минут, затем «Перерыв» — 5 минут и т.д.. Следовательно, расписание (схема) — это упорядоченный набор временных интервалов. Схема тоже может иметь своё имя. Например, «Усиленный режим работы» или «Стандартный режим».

struct TimeScheme {
	char* name;
	std::vector<TimeStamp> st;
};

Что должен уметь скрипт?

  • Создавать схему
  • Добавлять в схему (или расписание) временной промежуток
  • Выводить оповещение с нужным текстом и иконкой
  • Воспроизводить схему
  • Использовать диалоговое сообщение о продолжении или окончании работы

Как мы знаем из предыдущей статьи, систему оповещения notify нужно инициализировать перед использованием. Для этого, как и для действий, указанных выше, следует определить функцию. К тому же, в ходе инициализации можно указать имя приложения.

Определим функцию инициализации в основном исходнике:

void initNotify(const char* nname) {
	notify_init(nname);
	hNotification = notify_notification_new("", "", "dialog-information");
	notify_notification_set_timeout(hNotification, 1);
};

nname в данном случае — имя приложения (или группы оповещений). На данном этапе не важно — какие параметры мы передаем в функцию notify_notification_new, так как при каждом показе оповещения они будут меняться.

А теперь создадим соответствующий прототип функции initNotify для lua. Определим функцию в коде приложения, которую будет вызывать скрипт:

static int l_initNotify(lua_State* L) {
	const char* name = lua_tostring(L, 1);
	initNotify(name);
	return 0;
};

В первую очередь мы получаем первый аргумент, переданный из скрипта (считая, что это строка), затем вызываем нашу основную функцию с этим же аргументом. Параметр 0 — это количество возвращаемых в скрипт значений.

Последний этап — регистрация прототипа:

lua_pushcfunction(L, l_initNotify);
lua_setglobal(L, "initNotify");

Таким образом, если в скрипте встретиться функция с именем «initNotify«, lua вызовет соответствующую C-функцию.

Итоги

Все остальные функции из списка выше «экспортированы» в lua аналогичным образом. Кроме того, я посчитал целесообразным добавить функции воспроизведения звука на основе OpenAL. С примером программы и соответствующим скриптом можно ознакомиться здесь.

Добавить комментарий

Ваш e-mail не будет опубликован.