#include "TimerFileWatcher.h" #include #include #include #include #include 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; } g_usleep(500); } } 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) { }