Krolyxon
Commit 3724d3f

Branches

Refs →

nsxiv3724d3f

Revised autoreload interface

Make the header only contain the public interface and nothing from the
implementation. All functions get a handle to their self object, like the img_
and tns_ and win_ functions. All necessary data (file path) is also passed as
an argument, so that no extern redeclarations are needed.

Make arl_setup_dir() private, it's not called outside the module.

Make arl_handle() return true if the file has changed, so that the reloading of
the file can be done by the caller.
Author
Bert Münnich
Date
2017-05-17 20:07 +0200
Parent
edb117e
Commit
3724d3fc17dc6135a05608cab5bdf00c6978282d

+100 −91

4 files changed

  1. M autoreload.h +5 −13
  2. M autoreload_inotify.c +53 −57
  3. M autoreload_nop.c +22 −10
  4. M main.c +20 −11
M autoreload.h View
@@ -21,23 +21,15 @@
2121
2222 #include "types.h"
2323
24−void arl_cleanup(void);
25−void arl_handle(void);
26−void arl_init(void);
27−void arl_setup(void);
28−void arl_setup_dir(void);
29−
3024 typedef struct {
3125 int fd;
3226 int wd;
3327 bool watching_dir;
34−} autoreload_t;
35−
36−extern autoreload_t autoreload;
37−extern int fileidx;
38−extern fileinfo_t *files;
28+} arl_t;
3929
40−void load_image(int);
41−void redraw(void);
30+void arl_cleanup(arl_t*);
31+bool arl_handle(arl_t*, const char*);
32+void arl_init(arl_t*);
33+void arl_setup(arl_t*, const char*);
4234
4335 #endif /* AUTORELOAD_H */
M autoreload_inotify.c View
@@ -21,35 +21,59 @@
2121 #include <unistd.h>
2222 #include <sys/inotify.h>
2323 #include <libgen.h>
24−#include <time.h>
2524
2625 #include "util.h"
2726 #include "autoreload.h"
2827
29−const struct timespec ten_ms = {0, 10000000};
30−
31−void arl_cleanup(void)
28+CLEANUP void arl_cleanup(arl_t *arl)
3229 {
33− if (autoreload.fd != -1 && autoreload.wd != -1)
30+ if (arl->fd != -1 && arl->wd != -1)
3431 {
35− if(inotify_rm_watch(autoreload.fd, autoreload.wd))
32+ if(inotify_rm_watch(arl->fd, arl->wd))
3633 error(0, 0, "Failed to remove inotify watch.");
3734 }
3835 }
3936
40−void arl_handle(void)
37+static void arl_setup_dir(arl_t *arl, const char *filepath)
38+{
39+ char *dntmp, *dn;
40+
41+ if (arl->fd == -1)
42+ {
43+ error(0, 0, "Uninitialized, could not add inotify watch on directory.");
44+ return;
45+ }
46+
47+ /* get dirname */
48+ dntmp = (char*) strdup(filepath);
49+ dn = (char*) dirname(dntmp);
50+
51+ /* this is not one-shot as other stuff may be created too
52+ note: we won't handle deletion of the directory itself,
53+ this is a design decision */
54+ arl->wd = inotify_add_watch(arl->fd, dn,IN_CREATE);
55+ if (arl->wd == -1)
56+ error(0, 0, "Failed to add inotify watch on directory '%s'.", dn);
57+ else
58+ arl->watching_dir = true;
59+
60+ free(dntmp);
61+}
62+
63+bool arl_handle(arl_t *arl, const char *filepath)
4164 {
65+ bool reload = false;
4266 ssize_t len;
4367 char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
4468 const struct inotify_event *event;
4569 char *ptr;
4670 char *fntmp, *fn;
4771
48− len = read(autoreload.fd, buf, sizeof buf);
72+ len = read(arl->fd, buf, sizeof buf);
4973 if (len == -1)
5074 {
5175 error(0, 0, "Failed to read inotify events.");
52− return;
76+ return false;
5377 }
5478
5579 for (ptr = buf; ptr < buf + len;
@@ -61,17 +85,16 @@ void arl_handle(void)
6185 /* events from watching the file itself */
6286 if (event->mask & IN_CLOSE_WRITE)
6387 {
64− load_image(fileidx);
65− redraw();
88+ reload = true;
6689 }
6790
6891 if (event->mask & IN_DELETE_SELF)
69− arl_setup_dir();
92+ arl_setup_dir(arl, filepath);
7093
7194 /* events from watching the file's directory */
7295 if (event->mask & IN_CREATE)
7396 {
74− fntmp = strdup(files[fileidx].path);
97+ fntmp = strdup(filepath);
7598 fn = basename(fntmp);
7699
77100 if (0 == strcmp(event->name, fn))
@@ -79,76 +102,49 @@ void arl_handle(void)
79102 /* this is the file we're looking for */
80103
81104 /* cleanup, this has not been one-shot */
82− if (autoreload.watching_dir)
105+ if (arl->watching_dir)
83106 {
84− if(inotify_rm_watch(autoreload.fd, autoreload.wd))
107+ if(inotify_rm_watch(arl->fd, arl->wd))
85108 error(0, 0, "Failed to remove inotify watch.");
86− autoreload.watching_dir = false;
109+ arl->watching_dir = false;
87110 }
88111
89− /* when too fast, imlib2 can't load the image */
90− nanosleep(&ten_ms, NULL);
91− load_image(fileidx);
92− redraw();
112+ reload = true;
93113 }
94114 free(fntmp);
95115 }
96116 }
117+ return reload;
97118 }
98119
99−void arl_init(void)
120+void arl_init(arl_t *arl)
100121 {
101122 /* this needs to be done only once */
102− autoreload.fd = inotify_init();
103− autoreload.watching_dir = false;
104− if (autoreload.fd == -1)
123+ arl->fd = inotify_init();
124+ arl->watching_dir = false;
125+ if (arl->fd == -1)
105126 error(0, 0, "Could not initialize inotify.");
106127 }
107128
108−void arl_setup(void)
129+void arl_setup(arl_t *arl, const char *filepath)
109130 {
110− if (autoreload.fd == -1)
131+ if (arl->fd == -1)
111132 {
112133 error(0, 0, "Uninitialized, could not add inotify watch.");
113134 return;
114135 }
115136
116137 /* may have switched from a deleted to another image */
117− if (autoreload.watching_dir)
138+ if (arl->watching_dir)
118139 {
119− if (inotify_rm_watch(autoreload.fd, autoreload.wd))
140+ if (inotify_rm_watch(arl->fd, arl->wd))
120141 error(0, 0, "Failed to remove inotify watch.");
121− autoreload.watching_dir = false;
142+ arl->watching_dir = false;
122143 }
123144
124− autoreload.wd = inotify_add_watch(autoreload.fd, files[fileidx].path,
145+ arl->wd = inotify_add_watch(arl->fd, filepath,
125146 IN_ONESHOT | IN_CLOSE_WRITE | IN_DELETE_SELF);
126− if (autoreload.wd == -1)
127− error(0, 0, "Failed to add inotify watch on file '%s'.", files[fileidx].path);
147+ if (arl->wd == -1)
148+ error(0, 0, "Failed to add inotify watch on file '%s'.", filepath);
128149 }
129150
130−void arl_setup_dir(void)
131−{
132− char *dntmp, *dn;
133−
134− if (autoreload.fd == -1)
135− {
136− error(0, 0, "Uninitialized, could not add inotify watch on directory.");
137− return;
138− }
139−
140− /* get dirname */
141− dntmp = (char*) strdup(files[fileidx].path);
142− dn = (char*) dirname(dntmp);
143−
144− /* this is not one-shot as other stuff may be created too
145− note: we won't handle deletion of the directory itself,
146− this is a design decision */
147− autoreload.wd = inotify_add_watch(autoreload.fd, dn,IN_CREATE);
148− if (autoreload.wd == -1)
149− error(0, 0, "Failed to add inotify watch on directory '%s'.", dn);
150− else
151− autoreload.watching_dir = true;
152−
153− free(dntmp);
154−}
M autoreload_nop.c View
@@ -18,14 +18,26 @@
1818
1919 #include "autoreload.h"
2020
21−void arl_cleanup(void) { }
22−
23−void arl_handle(void) { }
24−
25−void arl_init(void) { }
26−
27−void arl_setup(void) { }
28−
29−void arl_setup_dir(void) { }
30−
21+void arl_cleanup(arl_t *arl)
22+{
23+ (void) arl;
24+}
25+
26+bool arl_handle(arl_t *arl, const char *filepath)
27+{
28+ (void) arl;
29+ (void) filepath;
30+ return false;
31+}
32+
33+void arl_init(arl_t *arl)
34+{
35+ (void) arl;
36+}
37+
38+void arl_setup(arl_t *arl, const char *filepath)
39+{
40+ (void) arl;
41+ (void) filepath;
42+}
3143
M main.c View
@@ -28,6 +28,7 @@
2828 #include <sys/stat.h>
2929 #include <sys/time.h>
3030 #include <sys/wait.h>
31+#include <time.h>
3132 #include <X11/keysym.h>
3233 #include <X11/XF86keysym.h>
3334
@@ -57,6 +58,7 @@ void slideshow(void);
5758 void clear_resize(void);
5859
5960 appmode_t mode;
61+arl_t arl;
6062 img_t img;
6163 tns_t tns;
6264 win_t win;
@@ -65,7 +67,6 @@ fileinfo_t *files;
6567 int filecnt, fileidx;
6668 int alternate;
6769 int markcnt;
68−autoreload_t autoreload;
6970
7071 int prefix;
7172 bool extprefix;
@@ -100,7 +101,7 @@ timeout_t timeouts[] = {
100101 void cleanup(void)
101102 {
102103 img_close(&img, false);
103− arl_cleanup();
104+ arl_cleanup(&arl);
104105 tns_free(&tns);
105106 win_close(&win);
106107 }
@@ -320,7 +321,7 @@ void load_image(int new)
320321
321322 info.open = false;
322323 open_info();
323− arl_setup();
324+ arl_setup(&arl, files[fileidx].path);
324325
325326 if (img.multi.cnt > 0 && img.multi.animate)
326327 set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
@@ -676,6 +677,8 @@ void on_buttonpress(XButtonEvent *bev)
676677 prefix = 0;
677678 }
678679
680+const struct timespec ten_ms = {0, 10000000};
681+
679682 void run(void)
680683 {
681684 int xfd;
@@ -689,8 +692,8 @@ void run(void)
689692 init_thumb = mode == MODE_THUMB && tns.initnext < filecnt;
690693 load_thumb = mode == MODE_THUMB && tns.loadnext < tns.end;
691694
692− if ((init_thumb || load_thumb || to_set || info.fd != -1 || autoreload.fd != -1) &&
693− XPending(win.env.dpy) == 0)
695+ if ((init_thumb || load_thumb || to_set || info.fd != -1 ||
696+ arl.fd != -1) && XPending(win.env.dpy) == 0)
694697 {
695698 if (load_thumb) {
696699 set_timeout(redraw, TO_REDRAW_THUMBS, false);
@@ -712,15 +715,21 @@ void run(void)
712715 FD_SET(info.fd, &fds);
713716 xfd = MAX(xfd, info.fd);
714717 }
715− if (autoreload.fd != -1) {
716− FD_SET(autoreload.fd, &fds);
717− xfd = MAX(xfd, autoreload.fd);
718+ if (arl.fd != -1) {
719+ FD_SET(arl.fd, &fds);
720+ xfd = MAX(xfd, arl.fd);
718721 }
719722 select(xfd + 1, &fds, 0, 0, to_set ? &timeout : NULL);
720723 if (info.fd != -1 && FD_ISSET(info.fd, &fds))
721724 read_info();
722− if (autoreload.fd != -1 && FD_ISSET(autoreload.fd, &fds))
723− arl_handle();
725+ if (arl.fd != -1 && FD_ISSET(arl.fd, &fds)) {
726+ if (arl_handle(&arl, files[fileidx].path)) {
727+ /* when too fast, imlib2 can't load the image */
728+ nanosleep(&ten_ms, NULL);
729+ load_image(fileidx);
730+ redraw();
731+ }
732+ }
724733 }
725734 continue;
726735 }
@@ -864,7 +873,7 @@ int main(int argc, char **argv)
864873
865874 win_init(&win);
866875 img_init(&img, &win);
867− arl_init();
876+ arl_init(&arl);
868877
869878 if ((homedir = getenv("XDG_CONFIG_HOME")) == NULL || homedir[0] == '\0') {
870879 homedir = getenv("HOME");