TimerFileWatcher.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include "TimerFileWatcher.h"
  2. #include <glib.h>
  3. #include <glib/gstdio.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <time.h>
  7. struct _TimerFileWatcher {
  8. GObject parent;
  9. char *path;
  10. GThread *thread;
  11. gboolean running;
  12. time_t lastTime;
  13. };
  14. G_DEFINE_TYPE(TimerFileWatcher, timer_file_watcher, G_TYPE_OBJECT);
  15. static void timer_file_watcher_tick(TimerFileWatcher *self) {
  16. gint64 last_tick = 0;
  17. GStatBuf statbuf;
  18. while (self->running) {
  19. gint64 now = g_get_monotonic_time();
  20. if ((now - last_tick) > (G_USEC_PER_SEC * FILE_WATCHER_POLL_RATE) && g_stat(self->path, &statbuf) == 0) {
  21. if (self->lastTime != statbuf.st_atime) {
  22. g_signal_emit_by_name(self, "file-changed");
  23. self->lastTime = statbuf.st_atime;
  24. }
  25. last_tick = now;
  26. }
  27. g_usleep(500);
  28. }
  29. }
  30. TimerFileWatcher *timer_file_watcher_new(const char *path) {
  31. TimerFileWatcher *fw = g_object_new(TIMER_TYPE_FILE_WATCHER, NULL);
  32. GStatBuf statbuf;
  33. if (g_stat(path, &statbuf) == 0) {
  34. fw->lastTime = statbuf.st_atime;
  35. }
  36. fw->path = g_strdup(path);
  37. fw->running = TRUE;
  38. fw->thread = g_thread_new(NULL, (GThreadFunc) timer_file_watcher_tick, fw);
  39. return fw;
  40. }
  41. const char *timer_file_watcher_get_path(TimerFileWatcher* self) {
  42. return self->path;
  43. }
  44. void timer_file_watcher_pause(TimerFileWatcher *self) {
  45. if (self->running) {
  46. self->running = FALSE;
  47. g_thread_join(self->thread);
  48. g_thread_unref(self->thread);
  49. }
  50. }
  51. void timer_file_watcher_resume(TimerFileWatcher *self, gboolean update) {
  52. if (!self->running) {
  53. self->running = TRUE;
  54. if (!update) {
  55. GStatBuf statbuf;
  56. if (g_stat(self->path, &statbuf) == 0) {
  57. self->lastTime = statbuf.st_atime;
  58. }
  59. }
  60. self->thread = g_thread_new(NULL, (GThreadFunc) timer_file_watcher_tick, self);
  61. }
  62. }
  63. gboolean timer_file_watcher_is_paused(TimerFileWatcher *self) {
  64. return !self->running;
  65. }
  66. static void timer_file_watcher_finalize(GObject *self) {
  67. g_free(TIMER_FILE_WATCHER(self)->path);
  68. timer_file_watcher_pause(TIMER_FILE_WATCHER(self));
  69. G_OBJECT_CLASS(timer_file_watcher_parent_class)->finalize(self);
  70. }
  71. static void timer_file_watcher_class_init(TimerFileWatcherClass *class) {
  72. g_signal_new("file-changed", TIMER_TYPE_FILE_WATCHER, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
  73. 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
  74. G_OBJECT_CLASS(class)->finalize = timer_file_watcher_finalize;
  75. }
  76. static void timer_file_watcher_init(TimerFileWatcher *self) {
  77. }