60 throw runtime_error(
"Could not init inotify system: " +
61 string(strerror(errno)));
68 for (
auto data : _image_data)
74 for (
auto &[fd, fn] : _inwds) {
75 inotify_rm_watch(_infd, fd);
81 void info(ostream &out = cout)
override {
83 out <<
" Watched files: " << style::bold;
84 for (
auto &[k, v] : _watch_list) {
85 out << k <<
": " << v <<
"; ";
87 out << style::reset << endl;
95 string topic, path, type;
100 if (kevent(_kq, NULL, 0, &change, 1, NULL) == -1) {
106 type = path.substr(path.find_last_of(
".") + 1);
107 cout <<
"Change detected to image '" << topic <<
"' at " << path
108 <<
" (type " << type <<
")" << endl;
112 char buffer[EVENT_BUF_LEN];
113 length = read(_infd, buffer, EVENT_BUF_LEN);
114 if (length < 0 && errno == EAGAIN) {
117 if (length < 0 && errno != EAGAIN) {
118 throw runtime_error(
"Error watching file changes: " +
119 string(strerror(errno)));
121 struct inotify_event *
event = (
struct inotify_event *)&buffer;
122 if (event->mask & IN_MODIFY) {
123 topic = _inwds[
event->wd];
124 path = _watch_list[_inwds[
event->wd]];
125 type = path.substr(path.find_last_of(
".") + 1);
126 cout <<
"Change detected to topic '" << topic <<
"' at " << path
127 <<
" (type " << type <<
")" << endl;
129 throw runtime_error(
"Unexpected event: "s + to_string(event->mask) +
130 " for " +
string(event->name));
134 json meta{{
"format", type}};
137 filebuf *pbuf = fin.rdbuf();
139 size_t size = pbuf->pubseekoff(0, fin.end, fin.in);
140 pbuf->pubseekpos(0, fin.in);
142 char *filebuffer =
new char[size];
144 pbuf->sgetn(filebuffer, size);
145 publish(filebuffer, size, meta, topic);
157 void load_settings()
override {
160 unsigned int count = 0;
164 if (!cfg[
"watch_list"].is_table()) {
165 throw std::runtime_error(
"No watch_list found in settings");
167 auto wl = cfg[
"watch_list"].as_table();
168 unsigned int n = wl->size();
169 _events = (
struct kevent *)calloc(n,
sizeof(
struct kevent));
170 wl->for_each([&](
const auto &k,
const auto &v) {
171 fname = v.value_or(
"undefined");
172 _fds.push_back(open(fname.c_str(), O_CREAT | O_RDONLY));
173 if (_fds.back() >= 0) {
174 _watch_list[
static_cast<string>(k)] = fname;
176 throw std::runtime_error(
"File " + fname +
177 " not found (and cannot be created)");
179 _image_data.push_back((image_data_t *)malloc(
sizeof(image_data_t)));
180 _image_data.back()->id = count++;
181 strcpy(_image_data.back()->topic,
static_cast<string>(k).c_str());
182 strcpy(_image_data.back()->path, fname.c_str());
183 EV_SET(&_events[i++], _fds.back(), EVFILT_VNODE,
184 EV_ADD | EV_CLEAR | EV_ENABLE, NOTE_WRITE, 0,
185 (
void *)(_image_data.back()));
187 kevent(_kq, _events, n, NULL, 0, NULL);
190 cfg[
"watch_list"].as_table()->for_each([&](
const auto &k,
const auto &v) {
191 fname = v.value_or(
"undefined");
192 topic =
static_cast<string>(k);
193 _watch_list[topic] = fname;
194 _image_data.push_back((image_data_t *)malloc(
sizeof(image_data_t)));
195 _image_data.back()->id = count++;
196 strcpy(_image_data.back()->topic, topic.c_str());
197 strcpy(_image_data.back()->path, fname.c_str());
198 count = inotify_add_watch(_infd, fname.c_str(), IN_MODIFY);
200 throw runtime_error(
"Inotify add watch error: " +
201 string(strerror(errno)));
203 _inwds[count] =
static_cast<string>(k);
208 map<string, string> _watch_list;
210 vector<image_data_t *> _image_data;
212 struct kevent *_events = NULL;
215 int _infd = inotify_init1(IN_NONBLOCK);
216 map<int, string> _inwds;