practice-timer/TimerFileWatcher.c

92 lines
2.6 KiB
C

#include "TimerFileWatcher.h"
#include <glib.h>
#include <glib/gstdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
struct _TimerFileWatcher {
GObject parent;
char *path;
GThread *thread;
gboolean running;
time_t lastTime;
};
G_DEFINE_TYPE(TimerFileWatcher, timer_file_watcher, G_TYPE_OBJECT);
static void timer_file_watcher_tick(TimerFileWatcher *self) {
gint64 last_tick = 0;
GStatBuf statbuf;
while (self->running) {
gint64 now = g_get_monotonic_time();
if ((now - last_tick) > (G_USEC_PER_SEC * FILE_WATCHER_POLL_RATE) && g_stat(self->path, &statbuf) == 0) {
if (self->lastTime != statbuf.st_atime) {
g_signal_emit_by_name(self, "file-changed");
self->lastTime = statbuf.st_atime;
}
last_tick = now;
}
}
}
TimerFileWatcher *timer_file_watcher_new(const char *path) {
TimerFileWatcher *fw = g_object_new(TIMER_TYPE_FILE_WATCHER, NULL);
GStatBuf statbuf;
if (g_stat(path, &statbuf) == 0) {
fw->lastTime = statbuf.st_atime;
}
fw->path = g_strdup(path);
fw->running = TRUE;
fw->thread = g_thread_new(NULL, (GThreadFunc) timer_file_watcher_tick, fw);
return fw;
}
const char *timer_file_watcher_get_path(TimerFileWatcher* self) {
return self->path;
}
void timer_file_watcher_pause(TimerFileWatcher *self) {
if (self->running) {
self->running = FALSE;
g_thread_join(self->thread);
g_thread_unref(self->thread);
}
}
void timer_file_watcher_resume(TimerFileWatcher *self, gboolean update) {
if (!self->running) {
self->running = TRUE;
if (!update) {
GStatBuf statbuf;
if (g_stat(self->path, &statbuf) == 0) {
self->lastTime = statbuf.st_atime;
}
}
self->thread = g_thread_new(NULL, (GThreadFunc) timer_file_watcher_tick, self);
}
}
gboolean timer_file_watcher_is_paused(TimerFileWatcher *self) {
return !self->running;
}
static void timer_file_watcher_finalize(GObject *self) {
g_free(TIMER_FILE_WATCHER(self)->path);
timer_file_watcher_pause(TIMER_FILE_WATCHER(self));
G_OBJECT_CLASS(timer_file_watcher_parent_class)->finalize(self);
}
static void timer_file_watcher_class_init(TimerFileWatcherClass *class) {
g_signal_new("file-changed", TIMER_TYPE_FILE_WATCHER, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
G_OBJECT_CLASS(class)->finalize = timer_file_watcher_finalize;
}
static void timer_file_watcher_init(TimerFileWatcher *self) {
}