nsxiv47af0dd
Cache out of view thumbnails in the background
+45 −25
5 files changed
- M commands.c +1 −1
- M main.c +15 −9
- M thumbs.c +22 −10
- M thumbs.h +4 −3
- M types.h +3 −2
| @@ -126,7 +126,7 @@ bool cg_reload_image(arg_t a) | |||
| 126 | 126 | load_image(fileidx); | |
| 127 | 127 | } else { | |
| 128 | 128 | win_set_cursor(&win, CURSOR_WATCH); | |
| 129 | − | if (!tns_load(&tns, fileidx, true)) { | |
| 129 | + | if (!tns_load(&tns, fileidx, true, false)) { | |
| 130 | 130 | remove_file(fileidx, false); | |
| 131 | 131 | tns.dirty = true; | |
| 132 | 132 | } | |
| @@ -385,7 +385,10 @@ void update_info(void) | |||
| 385 | 385 | r->p = r->buf; | |
| 386 | 386 | if (mode == MODE_THUMB) { | |
| 387 | 387 | if (tns.loadnext < tns.end) { | |
| 388 | − | bar_put(l, "Loading... %0*d", fw, MAX(tns.loadnext, 1)); | |
| 388 | + | bar_put(l, "Loading... %0*d", fw, tns.loadnext + 1); | |
| 389 | + | ow_info = false; | |
| 390 | + | } else if (tns.initnext < filecnt) { | |
| 391 | + | bar_put(l, "Caching... %0*d", fw, tns.initnext + 1); | |
| 389 | 392 | ow_info = false; | |
| 390 | 393 | } else { | |
| 391 | 394 | ow_info = true; | |
| @@ -453,7 +456,7 @@ void reset_cursor(void) | |||
| 453 | 456 | } | |
| 454 | 457 | } | |
| 455 | 458 | } else { | |
| 456 | − | if (tns.loadnext < tns.end) | |
| 459 | + | if (tns.loadnext < tns.end || tns.initnext < filecnt) | |
| 457 | 460 | cursor = CURSOR_WATCH; | |
| 458 | 461 | else | |
| 459 | 462 | cursor = CURSOR_ARROW; | |
| @@ -694,26 +697,29 @@ void run(void) | |||
| 694 | 697 | int xfd; | |
| 695 | 698 | fd_set fds; | |
| 696 | 699 | struct timeval timeout; | |
| 697 | − | bool discard, load_thumb, to_set; | |
| 700 | + | bool discard, init_thumb, load_thumb, to_set; | |
| 698 | 701 | XEvent ev, nextev; | |
| 699 | 702 | ||
| 700 | 703 | while (true) { | |
| 701 | 704 | to_set = check_timeouts(&timeout); | |
| 705 | + | init_thumb = mode == MODE_THUMB && tns.initnext < filecnt; | |
| 702 | 706 | load_thumb = mode == MODE_THUMB && tns.loadnext < tns.end; | |
| 703 | 707 | ||
| 704 | − | if ((load_thumb || to_set || info.fd != -1) && | |
| 708 | + | if ((init_thumb || load_thumb || to_set || info.fd != -1) && | |
| 705 | 709 | XPending(win.env.dpy) == 0) | |
| 706 | 710 | { | |
| 707 | 711 | if (load_thumb) { | |
| 708 | 712 | set_timeout(redraw, TO_REDRAW_THUMBS, false); | |
| 709 | − | if (!tns_load(&tns, tns.loadnext, false)) { | |
| 713 | + | if (!tns_load(&tns, tns.loadnext, false, false)) { | |
| 710 | 714 | remove_file(tns.loadnext, false); | |
| 711 | 715 | tns.dirty = true; | |
| 712 | 716 | } | |
| 713 | − | while (tns.loadnext < tns.end && tns.thumbs[tns.loadnext].im != NULL) | |
| 714 | − | tns.loadnext++; | |
| 715 | 717 | if (tns.loadnext >= tns.end) | |
| 716 | 718 | redraw(); | |
| 719 | + | } else if (init_thumb) { | |
| 720 | + | set_timeout(redraw, TO_REDRAW_THUMBS, false); | |
| 721 | + | if (!tns_load(&tns, tns.initnext, false, true)) | |
| 722 | + | remove_file(tns.initnext, false); | |
| 717 | 723 | } else { | |
| 718 | 724 | xfd = ConnectionNumber(win.env.dpy); | |
| 719 | 725 | FD_ZERO(&fds); | |
| @@ -899,8 +905,8 @@ int main(int argc, char **argv) | |||
| 899 | 905 | if (options->thumb_mode) { | |
| 900 | 906 | mode = MODE_THUMB; | |
| 901 | 907 | tns_init(&tns, files, &filecnt, &fileidx, &win); | |
| 902 | − | while (!tns_load(&tns, 0, false)) | |
| 903 | − | remove_file(0, false); | |
| 908 | + | while (!tns_load(&tns, fileidx, false, false)) | |
| 909 | + | remove_file(fileidx, false); | |
| 904 | 910 | } else { | |
| 905 | 911 | mode = MODE_IMAGE; | |
| 906 | 912 | tns.thumbs = NULL; | |
| @@ -152,7 +152,7 @@ void tns_clean_cache(tns_t *tns) | |||
| 152 | 152 | } | |
| 153 | 153 | ||
| 154 | 154 | ||
| 155 | − | void tns_init(tns_t *tns, const fileinfo_t *files, const int *cnt, int *sel, | |
| 155 | + | void tns_init(tns_t *tns, fileinfo_t *files, const int *cnt, int *sel, | |
| 156 | 156 | win_t *win) | |
| 157 | 157 | { | |
| 158 | 158 | int len; | |
| @@ -169,7 +169,8 @@ void tns_init(tns_t *tns, const fileinfo_t *files, const int *cnt, int *sel, | |||
| 169 | 169 | } | |
| 170 | 170 | tns->files = files; | |
| 171 | 171 | tns->cnt = cnt; | |
| 172 | − | tns->loadnext = tns->first = tns->end = tns->r_first = tns->r_end = 0; | |
| 172 | + | tns->initnext = tns->loadnext = 0; | |
| 173 | + | tns->first = tns->end = tns->r_first = tns->r_end = 0; | |
| 173 | 174 | tns->sel = sel; | |
| 174 | 175 | tns->win = win; | |
| 175 | 176 | tns->dirty = false; | |
| @@ -237,7 +238,7 @@ Imlib_Image tns_scale_down(Imlib_Image im, int dim) | |||
| 237 | 238 | return im; | |
| 238 | 239 | } | |
| 239 | 240 | ||
| 240 | − | bool tns_load(tns_t *tns, int n, bool force) | |
| 241 | + | bool tns_load(tns_t *tns, int n, bool force, bool cache_only) | |
| 241 | 242 | { | |
| 242 | 243 | int w, h; | |
| 243 | 244 | int maxwh = thumb_sizes[ARRLEN(thumb_sizes)-1]; | |
| @@ -245,8 +246,8 @@ bool tns_load(tns_t *tns, int n, bool force) | |||
| 245 | 246 | char *cfile; | |
| 246 | 247 | float zw, zh; | |
| 247 | 248 | thumb_t *t; | |
| 249 | + | fileinfo_t *file; | |
| 248 | 250 | Imlib_Image im = NULL; | |
| 249 | − | const fileinfo_t *file; | |
| 250 | 251 | ||
| 251 | 252 | if (tns == NULL || tns->thumbs == NULL) | |
| 252 | 253 | return false; | |
| @@ -261,6 +262,7 @@ bool tns_load(tns_t *tns, int n, bool force) | |||
| 261 | 262 | if (t->im != NULL) { | |
| 262 | 263 | imlib_context_set_image(t->im); | |
| 263 | 264 | imlib_free_image(); | |
| 265 | + | t->im = NULL; | |
| 264 | 266 | } | |
| 265 | 267 | ||
| 266 | 268 | if (!force) { | |
| @@ -345,10 +347,10 @@ bool tns_load(tns_t *tns, int n, bool force) | |||
| 345 | 347 | warn("could not open image: %s", file->name); | |
| 346 | 348 | return false; | |
| 347 | 349 | } | |
| 350 | + | imlib_context_set_image(im); | |
| 348 | 351 | ||
| 349 | 352 | if (!cache_hit) { | |
| 350 | 353 | #if HAVE_LIBEXIF | |
| 351 | − | imlib_context_set_image(im); | |
| 352 | 354 | exif_auto_orientate(file); | |
| 353 | 355 | #endif | |
| 354 | 356 | im = tns_scale_down(im, maxwh); | |
| @@ -357,12 +359,22 @@ bool tns_load(tns_t *tns, int n, bool force) | |||
| 357 | 359 | tns_cache_write(im, file->path, true); | |
| 358 | 360 | } | |
| 359 | 361 | ||
| 360 | − | t->im = tns_scale_down(im, thumb_sizes[tns->zl]); | |
| 361 | − | imlib_context_set_image(t->im); | |
| 362 | − | t->w = imlib_image_get_width(); | |
| 363 | − | t->h = imlib_image_get_height(); | |
| 362 | + | if (cache_only) { | |
| 363 | + | imlib_free_image_and_decache(); | |
| 364 | + | } else { | |
| 365 | + | t->im = tns_scale_down(im, thumb_sizes[tns->zl]); | |
| 366 | + | imlib_context_set_image(t->im); | |
| 367 | + | t->w = imlib_image_get_width(); | |
| 368 | + | t->h = imlib_image_get_height(); | |
| 369 | + | tns->dirty = true; | |
| 370 | + | } | |
| 371 | + | file->flags |= FF_TN_INIT; | |
| 372 | + | ||
| 373 | + | if (n == tns->initnext) | |
| 374 | + | while (++tns->initnext < *tns->cnt && ((++file)->flags & FF_TN_INIT)); | |
| 375 | + | if (n == tns->loadnext && !cache_only) | |
| 376 | + | while (++tns->loadnext < tns->end && (++t)->im != NULL); | |
| 364 | 377 | ||
| 365 | − | tns->dirty = true; | |
| 366 | 378 | return true; | |
| 367 | 379 | } | |
| 368 | 380 | ||
| @@ -34,10 +34,11 @@ typedef struct { | |||
| 34 | 34 | } thumb_t; | |
| 35 | 35 | ||
| 36 | 36 | typedef struct { | |
| 37 | − | const fileinfo_t *files; | |
| 37 | + | fileinfo_t *files; | |
| 38 | 38 | thumb_t *thumbs; | |
| 39 | 39 | const int *cnt; | |
| 40 | 40 | int *sel; | |
| 41 | + | int initnext; | |
| 41 | 42 | int loadnext; | |
| 42 | 43 | int first, end; | |
| 43 | 44 | int r_first, r_end; | |
| @@ -56,10 +57,10 @@ typedef struct { | |||
| 56 | 57 | ||
| 57 | 58 | void tns_clean_cache(tns_t*); | |
| 58 | 59 | ||
| 59 | − | void tns_init(tns_t*, const fileinfo_t*, const int*, int*, win_t*); | |
| 60 | + | void tns_init(tns_t*, fileinfo_t*, const int*, int*, win_t*); | |
| 60 | 61 | void tns_free(tns_t*); | |
| 61 | 62 | ||
| 62 | − | bool tns_load(tns_t*, int, bool); | |
| 63 | + | bool tns_load(tns_t*, int, bool, bool); | |
| 63 | 64 | void tns_unload(tns_t*, int); | |
| 64 | 65 | ||
| 65 | 66 | void tns_render(tns_t*); | |
| @@ -65,8 +65,9 @@ typedef enum { | |||
| 65 | 65 | } cursor_t; | |
| 66 | 66 | ||
| 67 | 67 | typedef enum { | |
| 68 | − | FF_WARN = 1, | |
| 69 | − | FF_MARK = 2 | |
| 68 | + | FF_WARN = 1, | |
| 69 | + | FF_MARK = 2, | |
| 70 | + | FF_TN_INIT = 4 | |
| 70 | 71 | } fileflags_t; | |
| 71 | 72 | ||
| 72 | 73 | typedef struct { | |