From 83bdf67d51c3f7ae996886c56556afe2a7f462e3 Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 7 Apr 2011 01:26:08 +0200 Subject: First things for thumbnail caching --- thumbs.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index da2adee..8e5e67e 100644 --- a/thumbs.c +++ b/thumbs.c @@ -18,6 +18,9 @@ #include #include +#include +#include +#include #include "config.h" #include "thumbs.h" @@ -26,6 +29,9 @@ extern Imlib_Image *im_invalid; const int thumb_dim = THUMB_SIZE + 10; +int tns_cache_enabled(); +void tns_cache_write(thumb_t*, Bool); + void tns_init(tns_t *tns, int cnt) { if (!tns) return; @@ -39,12 +45,17 @@ void tns_init(tns_t *tns, int cnt) { void tns_free(tns_t *tns, win_t *win) { int i; + Bool cache; if (!tns || !tns->thumbs) return; + cache = tns_cache_enabled(); + for (i = 0; i < tns->cnt; ++i) { if (tns->thumbs[i].im) { + if (cache) + tns_cache_write(&tns->thumbs[i], False); imlib_context_set_image(tns->thumbs[i].im); imlib_free_image(); } @@ -84,10 +95,12 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { h = imlib_image_get_height(); if (im) { + t->filename = filename; zw = (float) THUMB_SIZE / (float) w; zh = (float) THUMB_SIZE / (float) h; z = MIN(zw, zh); } else { + t->filename = NULL; z = 1.0; } @@ -278,3 +291,23 @@ int tns_translate(tns_t *tns, int x, int y) { return -1; } + +int tns_cache_enabled() { + int len, ret = 0; + char *cpath, *homedir; + struct stat stats; + + if ((homedir = getenv("HOME"))) { + len = strlen(homedir) + 10; + cpath = (char*) s_malloc(len * sizeof(char)); + snprintf(cpath, len, "%s/.sxiv", homedir); + ret = !stat(cpath, &stats) && S_ISDIR(stats.st_mode) && + !access(cpath, W_OK); + free(cpath); + } + + return ret; +} + +void tns_cache_write(thumb_t *t, Bool force) { +} -- cgit v1.2.3-70-g09d2 From c21a3e3f28a5c45497d09ab27d71538b983ca535 Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 7 Apr 2011 14:33:57 +0200 Subject: Write thumbnail cache files on exit --- thumbs.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- util.h | 7 ++++++ 3 files changed, 155 insertions(+), 1 deletion(-) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index 8e5e67e..e3c3f53 100644 --- a/thumbs.c +++ b/thumbs.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -292,6 +293,9 @@ int tns_translate(tns_t *tns, int x, int y) { return -1; } + +/* thumbnail caching */ + int tns_cache_enabled() { int len, ret = 0; char *cpath, *homedir; @@ -309,5 +313,70 @@ int tns_cache_enabled() { return ret; } +char* tns_cache_filename(const char *filename) { + size_t len; + int i; + char *cfile, *abspath, *homedir; + + if (!filename) + return NULL; + if (!(homedir = getenv("HOME"))) + return NULL; + + if (*filename != '/') { + if (!(abspath = absolute_path(filename))) + return NULL; + } else { + abspath = (char*) s_malloc(strlen(filename) + 1); + strcpy(abspath, filename); + } + + len = strlen(abspath); + for (i = 1; i < len; ++i) { + if (abspath[i] == '/') + abspath[i] = '%'; + } + + len += strlen(homedir) + 15; + cfile = (char*) s_malloc(len); + snprintf(cfile, len, "%s/.sxiv/%s.png", homedir, abspath + 1); + + free(abspath); + + return cfile; +} + void tns_cache_write(thumb_t *t, Bool force) { + char *cfile; + struct stat cstats, fstats; + struct timeval times[2]; + Imlib_Load_Error err; + + if (!t || !t->im || !t->filename) + return; + + if ((cfile = tns_cache_filename(t->filename))) { + if (stat(t->filename, &fstats)) + goto end; + + if (force || stat(cfile, &cstats) || + cstats.st_mtim.tv_sec != fstats.st_mtim.tv_sec || + cstats.st_mtim.tv_nsec != fstats.st_mtim.tv_nsec) + { + imlib_context_set_image(t->im); + imlib_image_set_format("png"); + imlib_save_image_with_error_return(cfile, &err); + + if (err) { + warn("could not cache thumbnail:", t->filename); + } else { + TIMESPEC_TO_TIMEVAL(×[0], &fstats.st_atim); + TIMESPEC_TO_TIMEVAL(×[1], &fstats.st_mtim); + utimes(cfile, times); + } + } + } + +end: + free(cfile); } diff --git a/util.c b/util.c index 5c5737b..f2302fd 100644 --- a/util.c +++ b/util.c @@ -18,11 +18,13 @@ #include #include +#include +#include #include "options.h" #include "util.h" -#define FNAME_LEN 512 +#define FNAME_LEN 1024 void cleanup(); @@ -78,6 +80,82 @@ void size_readable(float *size, const char **unit) { *unit = units[MIN(i, LEN(units) - 1)]; } +char* absolute_path(const char *filename) { + size_t len; + char *path = NULL; + const char *basename; + char *dirname = NULL; + char *cwd = NULL; + char *twd = NULL; + char *dir; + char *s; + + if (!filename || *filename == '\0' || *filename == '/') + return NULL; + + len = FNAME_LEN; + cwd = (char*) s_malloc(len); + while (!(s = getcwd(cwd, len)) && errno == ERANGE) { + len *= 2; + cwd = (char*) s_realloc(cwd, len); + } + if (!s) + goto error; + + s = strrchr(filename, '/'); + if (s) { + len = s - filename; + dirname = (char*) s_malloc(len + 1); + strncpy(dirname, filename, len); + dirname[len] = '\0'; + basename = s + 1; + + if (chdir(cwd)) + /* we're not able to come back afterwards */ + goto error; + if (chdir(dirname)) + goto error; + + len = FNAME_LEN; + twd = (char*) s_malloc(len); + while (!(s = getcwd(twd, len)) && errno == ERANGE) { + len *= 2; + twd = (char*) s_realloc(twd, len); + } + if (chdir(cwd)) + die("could not revert to working directory"); + if (!s) + goto error; + dir = twd; + } else { + /* only a single filename given */ + basename = filename; + dir = cwd; + } + + len = strlen(dir) + strlen(basename) + 2; + path = (char*) s_malloc(len); + snprintf(path, len, "%s/%s", dir, basename); + +goto end; + +error: + if (path) { + free(path); + path = NULL; + } + +end: + if (dirname) + free(dirname); + if (cwd) + free(cwd); + if (twd) + free(twd); + + return path; +} + char* readline(FILE *stream) { size_t len; char *buf, *s, *end; diff --git a/util.h b/util.h index f1db6b8..e3cdef9 100644 --- a/util.h +++ b/util.h @@ -30,6 +30,11 @@ #define TV_TO_DOUBLE(x) ((double) ((x).tv_sec) + 0.000001 * \ (double) ((x).tv_usec)) +#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ +} + void* s_malloc(size_t); void* s_realloc(void*, size_t); @@ -38,6 +43,8 @@ void die(const char*, ...); void size_readable(float*, const char**); +char* absolute_path(const char*); + char* readline(FILE*); #endif /* UTIL_H */ -- cgit v1.2.3-70-g09d2 From 1d0f51f95a5035f62b69bd85ef634e50f0e8c56e Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 7 Apr 2011 15:05:17 +0200 Subject: Load thumbnails from cache --- thumbs.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index e3c3f53..80c2361 100644 --- a/thumbs.c +++ b/thumbs.c @@ -31,6 +31,7 @@ extern Imlib_Image *im_invalid; const int thumb_dim = THUMB_SIZE + 10; int tns_cache_enabled(); +Imlib_Image* tns_cache_load(const char*); void tns_cache_write(thumb_t*, Bool); void tns_init(tns_t *tns, int cnt) { @@ -87,7 +88,8 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { imlib_free_image(); } - if ((im = imlib_load_image(filename))) + if ((tns_cache_enabled() && (im = tns_cache_load(filename))) || + (im = imlib_load_image(filename))) imlib_context_set_image(im); else imlib_context_set_image(im_invalid); @@ -346,6 +348,29 @@ char* tns_cache_filename(const char *filename) { return cfile; } +Imlib_Image* tns_cache_load(const char *filename) { + char *cfile; + struct stat cstats, fstats; + Imlib_Image *im = NULL; + + if (!filename || stat(filename, &fstats)) + return NULL; + + if ((cfile = tns_cache_filename(filename))) { + if (!stat(cfile, &cstats) && + cstats.st_mtim.tv_sec == fstats.st_mtim.tv_sec && + cstats.st_mtim.tv_nsec == fstats.st_mtim.tv_nsec) + { + printf("cache hit: %s\n", filename); + im = imlib_load_image(cfile); + } else + printf("cache MISS: %s\n", filename); + free(cfile); + } + + return im; +} + void tns_cache_write(thumb_t *t, Bool force) { char *cfile; struct stat cstats, fstats; @@ -354,11 +379,10 @@ void tns_cache_write(thumb_t *t, Bool force) { if (!t || !t->im || !t->filename) return; + if (stat(t->filename, &fstats)) + return; if ((cfile = tns_cache_filename(t->filename))) { - if (stat(t->filename, &fstats)) - goto end; - if (force || stat(cfile, &cstats) || cstats.st_mtim.tv_sec != fstats.st_mtim.tv_sec || cstats.st_mtim.tv_nsec != fstats.st_mtim.tv_nsec) @@ -373,10 +397,9 @@ void tns_cache_write(thumb_t *t, Bool force) { TIMESPEC_TO_TIMEVAL(×[0], &fstats.st_atim); TIMESPEC_TO_TIMEVAL(×[1], &fstats.st_mtim); utimes(cfile, times); + printf("thumbnail cache file written: %s\n", t->filename); } } + free(cfile); } - -end: - free(cfile); } -- cgit v1.2.3-70-g09d2 From f93f4d887cb17fe4d7e702cbf71a4f10b851b32f Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 7 Apr 2011 16:17:10 +0200 Subject: Write cache file for thumbnail directly after creating it --- thumbs.c | 20 +++++++++++--------- util.c | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index 80c2361..bbfda7b 100644 --- a/thumbs.c +++ b/thumbs.c @@ -47,17 +47,12 @@ void tns_init(tns_t *tns, int cnt) { void tns_free(tns_t *tns, win_t *win) { int i; - Bool cache; if (!tns || !tns->thumbs) return; - cache = tns_cache_enabled(); - for (i = 0; i < tns->cnt; ++i) { if (tns->thumbs[i].im) { - if (cache) - tns_cache_write(&tns->thumbs[i], False); imlib_context_set_image(tns->thumbs[i].im); imlib_free_image(); } @@ -69,6 +64,7 @@ void tns_free(tns_t *tns, win_t *win) { void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { int w, h; + int use_cache, cached = 0; float z, zw, zh; thumb_t *t; Imlib_Image *im; @@ -88,8 +84,12 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { imlib_free_image(); } - if ((tns_cache_enabled() && (im = tns_cache_load(filename))) || - (im = imlib_load_image(filename))) + if ((use_cache = tns_cache_enabled())) { + if ((im = tns_cache_load(filename))) + cached = 1; + } + + if (cached || (im = imlib_load_image(filename))) imlib_context_set_image(im); else imlib_context_set_image(im_invalid); @@ -115,6 +115,8 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { die("could not allocate memory"); if (im) imlib_free_image_and_decache(); + if (use_cache && !cached) + tns_cache_write(t, False); tns->dirty = 1; } @@ -334,7 +336,7 @@ char* tns_cache_filename(const char *filename) { } len = strlen(abspath); - for (i = 1; i < len; ++i) { + for (i = 0; i < len; ++i) { if (abspath[i] == '/') abspath[i] = '%'; } @@ -392,7 +394,7 @@ void tns_cache_write(thumb_t *t, Bool force) { imlib_save_image_with_error_return(cfile, &err); if (err) { - warn("could not cache thumbnail:", t->filename); + warn("could not cache thumbnail: %s", t->filename); } else { TIMESPEC_TO_TIMEVAL(×[0], &fstats.st_atim); TIMESPEC_TO_TIMEVAL(×[1], &fstats.st_mtim); diff --git a/util.c b/util.c index f2302fd..517b4ba 100644 --- a/util.c +++ b/util.c @@ -123,7 +123,7 @@ char* absolute_path(const char *filename) { twd = (char*) s_realloc(twd, len); } if (chdir(cwd)) - die("could not revert to working directory"); + die("could not revert to prior working directory"); if (!s) goto error; dir = twd; -- cgit v1.2.3-70-g09d2 From f52a99db6c1f0a659934a50ae4a4ef8085ee3752 Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 7 Apr 2011 17:23:47 +0200 Subject: Refactored thumbnail cache_dir --- thumbs.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index bbfda7b..6b37526 100644 --- a/thumbs.c +++ b/thumbs.c @@ -28,13 +28,18 @@ #include "util.h" extern Imlib_Image *im_invalid; + const int thumb_dim = THUMB_SIZE + 10; +char *cache_dir = NULL; int tns_cache_enabled(); Imlib_Image* tns_cache_load(const char*); void tns_cache_write(thumb_t*, Bool); void tns_init(tns_t *tns, int cnt) { + int len; + char *homedir; + if (!tns) return; @@ -43,6 +48,14 @@ void tns_init(tns_t *tns, int cnt) { memset(tns->thumbs, 0, cnt * sizeof(thumb_t)); tns->cap = cnt; tns->dirty = 0; + + if ((homedir = getenv("HOME"))) { + if (cache_dir) + free(cache_dir); + len = strlen(homedir) + 10; + cache_dir = (char*) s_malloc(len * sizeof(char)); + snprintf(cache_dir, len, "%s/.sxiv", homedir); + } } void tns_free(tns_t *tns, win_t *win) { @@ -60,6 +73,11 @@ void tns_free(tns_t *tns, win_t *win) { free(tns->thumbs); tns->thumbs = NULL; + + if (cache_dir) { + free(cache_dir); + cache_dir = NULL; + } } void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { @@ -301,30 +319,18 @@ int tns_translate(tns_t *tns, int x, int y) { /* thumbnail caching */ int tns_cache_enabled() { - int len, ret = 0; - char *cpath, *homedir; struct stat stats; - if ((homedir = getenv("HOME"))) { - len = strlen(homedir) + 10; - cpath = (char*) s_malloc(len * sizeof(char)); - snprintf(cpath, len, "%s/.sxiv", homedir); - ret = !stat(cpath, &stats) && S_ISDIR(stats.st_mode) && - !access(cpath, W_OK); - free(cpath); - } - - return ret; + return cache_dir && !stat(cache_dir, &stats) && S_ISDIR(stats.st_mode) && + !access(cache_dir, W_OK); } char* tns_cache_filename(const char *filename) { size_t len; int i; - char *cfile, *abspath, *homedir; + char *cfile, *abspath; - if (!filename) - return NULL; - if (!(homedir = getenv("HOME"))) + if (!cache_dir || !filename) return NULL; if (*filename != '/') { @@ -341,9 +347,9 @@ char* tns_cache_filename(const char *filename) { abspath[i] = '%'; } - len += strlen(homedir) + 15; + len += strlen(cache_dir) + 6; cfile = (char*) s_malloc(len); - snprintf(cfile, len, "%s/.sxiv/%s.png", homedir, abspath + 1); + snprintf(cfile, len, "%s/%s.png", cache_dir, abspath + 1); free(abspath); -- cgit v1.2.3-70-g09d2 From 92709b2b2f579300b1c007e5a3ba869e78fcc922 Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 7 Apr 2011 17:29:59 +0200 Subject: Use directory structure in cache dir --- thumbs.c | 27 ++++++++++++++------------- util.c | 43 +++++++++++++++++++++++++++++++++++++++++++ util.h | 1 + 3 files changed, 58 insertions(+), 13 deletions(-) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index 6b37526..820fd4b 100644 --- a/thumbs.c +++ b/thumbs.c @@ -327,7 +327,6 @@ int tns_cache_enabled() { char* tns_cache_filename(const char *filename) { size_t len; - int i; char *cfile, *abspath; if (!cache_dir || !filename) @@ -341,13 +340,7 @@ char* tns_cache_filename(const char *filename) { strcpy(abspath, filename); } - len = strlen(abspath); - for (i = 0; i < len; ++i) { - if (abspath[i] == '/') - abspath[i] = '%'; - } - - len += strlen(cache_dir) + 6; + len = strlen(cache_dir) + strlen(abspath) + 6; cfile = (char*) s_malloc(len); snprintf(cfile, len, "%s/%s.png", cache_dir, abspath + 1); @@ -380,10 +373,10 @@ Imlib_Image* tns_cache_load(const char *filename) { } void tns_cache_write(thumb_t *t, Bool force) { - char *cfile; + char *cfile, *dirend; struct stat cstats, fstats; struct timeval times[2]; - Imlib_Load_Error err; + Imlib_Load_Error err = 0; if (!t || !t->im || !t->filename) return; @@ -395,9 +388,17 @@ void tns_cache_write(thumb_t *t, Bool force) { cstats.st_mtim.tv_sec != fstats.st_mtim.tv_sec || cstats.st_mtim.tv_nsec != fstats.st_mtim.tv_nsec) { - imlib_context_set_image(t->im); - imlib_image_set_format("png"); - imlib_save_image_with_error_return(cfile, &err); + if ((dirend = strrchr(cfile, '/'))) { + *dirend = '\0'; + err = create_dir_rec(cfile); + *dirend = '/'; + } + + if (!err) { + imlib_context_set_image(t->im); + imlib_image_set_format("png"); + imlib_save_image_with_error_return(cfile, &err); + } if (err) { warn("could not cache thumbnail: %s", t->filename); diff --git a/util.c b/util.c index 517b4ba..42d1384 100644 --- a/util.c +++ b/util.c @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include @@ -156,6 +158,47 @@ end: return path; } +int create_dir_rec(const char *path) { + char *dir, *d; + struct stat stats; + int err = 0; + + if (!path || !*path) + return -1; + + if (!stat(path, &stats)) { + if (S_ISDIR(stats.st_mode)) { + return 0; + } else { + warn("not a directory: %s", path); + return -1; + } + } + + d = dir = (char*) s_malloc(strlen(path) + 1); + strcpy(dir, path); + + while (d != NULL && !err) { + d = strchr(d + 1, '/'); + if (d != NULL) + *d = '\0'; + if (access(dir, F_OK) && errno == ENOENT) { + if (mkdir(dir, 0755)) { + warn("could not create directory: %s", dir); + err = -1; + } + } else if (stat(dir, &stats) || !S_ISDIR(stats.st_mode)) { + warn("not a directory: %s", dir); + err = -1; + } + if (d != NULL) + *d = '/'; + } + free(dir); + + return err; +} + char* readline(FILE *stream) { size_t len; char *buf, *s, *end; diff --git a/util.h b/util.h index e3cdef9..b6efd5a 100644 --- a/util.h +++ b/util.h @@ -44,6 +44,7 @@ void die(const char*, ...); void size_readable(float*, const char**); char* absolute_path(const char*); +int create_dir_rec(const char*); char* readline(FILE*); -- cgit v1.2.3-70-g09d2 From 7d40faeba6076477645e36034b58e4bf82d4a96c Mon Sep 17 00:00:00 2001 From: Bert Date: Thu, 7 Apr 2011 18:00:01 +0200 Subject: Do not create cache files for cache files --- thumbs.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index 820fd4b..7c895c1 100644 --- a/thumbs.c +++ b/thumbs.c @@ -327,7 +327,8 @@ int tns_cache_enabled() { char* tns_cache_filename(const char *filename) { size_t len; - char *cfile, *abspath; + char *cfile = NULL; + const char *abspath; if (!cache_dir || !filename) return NULL; @@ -336,15 +337,17 @@ char* tns_cache_filename(const char *filename) { if (!(abspath = absolute_path(filename))) return NULL; } else { - abspath = (char*) s_malloc(strlen(filename) + 1); - strcpy(abspath, filename); + abspath = filename; } - len = strlen(cache_dir) + strlen(abspath) + 6; - cfile = (char*) s_malloc(len); - snprintf(cfile, len, "%s/%s.png", cache_dir, abspath + 1); + if (strncmp(abspath, cache_dir, strlen(cache_dir))) { + len = strlen(cache_dir) + strlen(abspath) + 6; + cfile = (char*) s_malloc(len); + snprintf(cfile, len, "%s/%s.png", cache_dir, abspath + 1); + } - free(abspath); + if (abspath != filename) + free((void*) abspath); return cfile; } -- cgit v1.2.3-70-g09d2 From eee921efe0959251daec3d23e652b4f3a924df92 Mon Sep 17 00:00:00 2001 From: Bert Date: Fri, 8 Apr 2011 10:24:10 +0200 Subject: Refactored thumbs.c --- thumbs.c | 202 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 98 insertions(+), 104 deletions(-) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index 7c895c1..2e28908 100644 --- a/thumbs.c +++ b/thumbs.c @@ -32,9 +32,104 @@ extern Imlib_Image *im_invalid; const int thumb_dim = THUMB_SIZE + 10; char *cache_dir = NULL; -int tns_cache_enabled(); -Imlib_Image* tns_cache_load(const char*); -void tns_cache_write(thumb_t*, Bool); +int tns_cache_enabled() { + struct stat stats; + + return cache_dir && !stat(cache_dir, &stats) && S_ISDIR(stats.st_mode) && + !access(cache_dir, W_OK); +} + +char* tns_cache_filename(const char *filename) { + size_t len; + char *cfile = NULL; + const char *abspath; + + if (!cache_dir || !filename) + return NULL; + + if (*filename != '/') { + if (!(abspath = absolute_path(filename))) + return NULL; + } else { + abspath = filename; + } + + if (strncmp(abspath, cache_dir, strlen(cache_dir))) { + len = strlen(cache_dir) + strlen(abspath) + 6; + cfile = (char*) s_malloc(len); + snprintf(cfile, len, "%s/%s.png", cache_dir, abspath + 1); + } + + if (abspath != filename) + free((void*) abspath); + + return cfile; +} + +Imlib_Image* tns_cache_load(const char *filename) { + char *cfile; + struct stat cstats, fstats; + Imlib_Image *im = NULL; + + if (!filename || stat(filename, &fstats)) + return NULL; + + if ((cfile = tns_cache_filename(filename))) { + if (!stat(cfile, &cstats) && + cstats.st_mtim.tv_sec == fstats.st_mtim.tv_sec && + cstats.st_mtim.tv_nsec == fstats.st_mtim.tv_nsec) + { + printf("cache hit: %s\n", filename); + im = imlib_load_image(cfile); + } else + printf("cache MISS: %s\n", filename); + free(cfile); + } + + return im; +} + +void tns_cache_write(thumb_t *t, Bool force) { + char *cfile, *dirend; + struct stat cstats, fstats; + struct timeval times[2]; + Imlib_Load_Error err = 0; + + if (!t || !t->im || !t->filename) + return; + if (stat(t->filename, &fstats)) + return; + + if ((cfile = tns_cache_filename(t->filename))) { + if (force || stat(cfile, &cstats) || + cstats.st_mtim.tv_sec != fstats.st_mtim.tv_sec || + cstats.st_mtim.tv_nsec != fstats.st_mtim.tv_nsec) + { + if ((dirend = strrchr(cfile, '/'))) { + *dirend = '\0'; + err = r_mkdir(cfile); + *dirend = '/'; + } + + if (!err) { + imlib_context_set_image(t->im); + imlib_image_set_format("png"); + imlib_save_image_with_error_return(cfile, &err); + } + + if (err) { + warn("could not cache thumbnail: %s", t->filename); + } else { + TIMESPEC_TO_TIMEVAL(×[0], &fstats.st_atim); + TIMESPEC_TO_TIMEVAL(×[1], &fstats.st_mtim); + utimes(cfile, times); + printf("thumbnail cache file written: %s\n", t->filename); + } + } + free(cfile); + } +} + void tns_init(tns_t *tns, int cnt) { int len; @@ -314,104 +409,3 @@ int tns_translate(tns_t *tns, int x, int y) { return -1; } - - -/* thumbnail caching */ - -int tns_cache_enabled() { - struct stat stats; - - return cache_dir && !stat(cache_dir, &stats) && S_ISDIR(stats.st_mode) && - !access(cache_dir, W_OK); -} - -char* tns_cache_filename(const char *filename) { - size_t len; - char *cfile = NULL; - const char *abspath; - - if (!cache_dir || !filename) - return NULL; - - if (*filename != '/') { - if (!(abspath = absolute_path(filename))) - return NULL; - } else { - abspath = filename; - } - - if (strncmp(abspath, cache_dir, strlen(cache_dir))) { - len = strlen(cache_dir) + strlen(abspath) + 6; - cfile = (char*) s_malloc(len); - snprintf(cfile, len, "%s/%s.png", cache_dir, abspath + 1); - } - - if (abspath != filename) - free((void*) abspath); - - return cfile; -} - -Imlib_Image* tns_cache_load(const char *filename) { - char *cfile; - struct stat cstats, fstats; - Imlib_Image *im = NULL; - - if (!filename || stat(filename, &fstats)) - return NULL; - - if ((cfile = tns_cache_filename(filename))) { - if (!stat(cfile, &cstats) && - cstats.st_mtim.tv_sec == fstats.st_mtim.tv_sec && - cstats.st_mtim.tv_nsec == fstats.st_mtim.tv_nsec) - { - printf("cache hit: %s\n", filename); - im = imlib_load_image(cfile); - } else - printf("cache MISS: %s\n", filename); - free(cfile); - } - - return im; -} - -void tns_cache_write(thumb_t *t, Bool force) { - char *cfile, *dirend; - struct stat cstats, fstats; - struct timeval times[2]; - Imlib_Load_Error err = 0; - - if (!t || !t->im || !t->filename) - return; - if (stat(t->filename, &fstats)) - return; - - if ((cfile = tns_cache_filename(t->filename))) { - if (force || stat(cfile, &cstats) || - cstats.st_mtim.tv_sec != fstats.st_mtim.tv_sec || - cstats.st_mtim.tv_nsec != fstats.st_mtim.tv_nsec) - { - if ((dirend = strrchr(cfile, '/'))) { - *dirend = '\0'; - err = create_dir_rec(cfile); - *dirend = '/'; - } - - if (!err) { - imlib_context_set_image(t->im); - imlib_image_set_format("png"); - imlib_save_image_with_error_return(cfile, &err); - } - - if (err) { - warn("could not cache thumbnail: %s", t->filename); - } else { - TIMESPEC_TO_TIMEVAL(×[0], &fstats.st_atim); - TIMESPEC_TO_TIMEVAL(×[1], &fstats.st_mtim); - utimes(cfile, times); - printf("thumbnail cache file written: %s\n", t->filename); - } - } - free(cfile); - } -} -- cgit v1.2.3-70-g09d2 From dc54981a68589c719937c82c36eeb9247d915a81 Mon Sep 17 00:00:00 2001 From: Bert Date: Fri, 8 Apr 2011 14:44:00 +0200 Subject: New option: -C, clean thumbnail cache --- main.c | 6 +++++ options.c | 8 ++++-- options.h | 1 + thumbs.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++------------ thumbs.h | 2 ++ 5 files changed, 83 insertions(+), 18 deletions(-) (limited to 'thumbs.c') diff --git a/main.c b/main.c index 51d97d4..ada0574 100644 --- a/main.c +++ b/main.c @@ -104,6 +104,12 @@ int main(int argc, char **argv) { parse_options(argc, argv); + if (options->clean_cache) { + tns_init(&tns, 0); + tns_clear_cache(&tns); + exit(0); + } + if (!options->filecnt) { print_usage(); exit(1); diff --git a/options.c b/options.c index f5066f4..8105485 100644 --- a/options.c +++ b/options.c @@ -31,7 +31,7 @@ options_t _options; const options_t *options = (const options_t*) &_options; void print_usage() { - printf("usage: sxiv [-adFfhpqrstvZ] [-g GEOMETRY] [-z ZOOM] FILES...\n"); + printf("usage: sxiv [-aCdFfhpqrstvZ] [-g GEOMETRY] [-z ZOOM] FILES...\n"); } void print_version() { @@ -53,9 +53,10 @@ void parse_options(int argc, char **argv) { _options.all = 0; _options.quiet = 0; + _options.clean_cache = 0; _options.recursive = 0; - while ((opt = getopt(argc, argv, "adFfg:hpqrstvZz:")) != -1) { + while ((opt = getopt(argc, argv, "aCdFfg:hpqrstvZz:")) != -1) { switch (opt) { case '?': print_usage(); @@ -63,6 +64,9 @@ void parse_options(int argc, char **argv) { case 'a': _options.all = 1; break; + case 'C': + _options.clean_cache = 1; + break; case 'd': _options.scalemode = SCALE_DOWN; break; diff --git a/options.h b/options.h index c32b50a..b7b8ba5 100644 --- a/options.h +++ b/options.h @@ -37,6 +37,7 @@ typedef struct { unsigned char all; unsigned char quiet; + unsigned char clean_cache; unsigned char recursive; } options_t; diff --git a/thumbs.c b/thumbs.c index 2e28908..abcfaaa 100644 --- a/thumbs.c +++ b/thumbs.c @@ -71,7 +71,10 @@ Imlib_Image* tns_cache_load(const char *filename) { struct stat cstats, fstats; Imlib_Image *im = NULL; - if (!filename || stat(filename, &fstats)) + if (!filename) + return NULL; + + if (stat(filename, &fstats)) return NULL; if ((cfile = tns_cache_filename(filename))) { @@ -97,6 +100,7 @@ void tns_cache_write(thumb_t *t, Bool force) { if (!t || !t->im || !t->filename) return; + if (stat(t->filename, &fstats)) return; @@ -130,6 +134,40 @@ void tns_cache_write(thumb_t *t, Bool force) { } } +void tns_clear_cache(tns_t *tns) { + int dirlen, delete; + char *cfile, *filename, *tpos; + r_dir_t dir; + + if (!cache_dir) + return; + + if (r_opendir(&dir, cache_dir)) { + warn("could not open thumbnail cache directory: %s", cache_dir); + return; + } + + dirlen = strlen(cache_dir); + + while ((cfile = r_readdir(&dir))) { + filename = cfile + dirlen; + delete = 0; + + if ((tpos = strrchr(filename, '.'))) { + *tpos = '\0'; + delete = access(filename, F_OK); + *tpos = '.'; + } + + if (delete && unlink(cfile)) + warn("could not delete cache file: %s", cfile); + + free(cfile); + } + + r_closedir(&dir); +} + void tns_init(tns_t *tns, int cnt) { int len; @@ -138,9 +176,14 @@ void tns_init(tns_t *tns, int cnt) { if (!tns) return; + if (cnt) { + tns->thumbs = (thumb_t*) s_malloc(cnt * sizeof(thumb_t)); + memset(tns->thumbs, 0, cnt * sizeof(thumb_t)); + } else { + tns->thumbs = NULL; + } + tns->cnt = tns->first = tns->sel = 0; - tns->thumbs = (thumb_t*) s_malloc(cnt * sizeof(thumb_t)); - memset(tns->thumbs, 0, cnt * sizeof(thumb_t)); tns->cap = cnt; tns->dirty = 0; @@ -150,25 +193,28 @@ void tns_init(tns_t *tns, int cnt) { len = strlen(homedir) + 10; cache_dir = (char*) s_malloc(len * sizeof(char)); snprintf(cache_dir, len, "%s/.sxiv", homedir); + } else { + warn("could not locate thumbnail cache directory"); } } void tns_free(tns_t *tns, win_t *win) { int i; - if (!tns || !tns->thumbs) + if (!tns) return; - for (i = 0; i < tns->cnt; ++i) { - if (tns->thumbs[i].im) { - imlib_context_set_image(tns->thumbs[i].im); - imlib_free_image(); + if (tns->thumbs) { + for (i = 0; i < tns->cnt; ++i) { + if (tns->thumbs[i].im) { + imlib_context_set_image(tns->thumbs[i].im); + imlib_free_image(); + } } + free(tns->thumbs); + tns->thumbs = NULL; } - free(tns->thumbs); - tns->thumbs = NULL; - if (cache_dir) { free(cache_dir); cache_dir = NULL; @@ -182,7 +228,7 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) { thumb_t *t; Imlib_Image *im; - if (!tns || !win || !filename) + if (!tns || !tns->thumbs || !win || !filename) return; if (n >= tns->cap) @@ -265,7 +311,10 @@ void tns_render(tns_t *tns, win_t *win) { int i, cnt, r, x, y; thumb_t *t; - if (!tns || !tns->dirty || !win) + if (!tns || !tns->thumbs || !win) + return; + + if (!tns->dirty) return; win_clear(win); @@ -313,7 +362,7 @@ void tns_highlight(tns_t *tns, win_t *win, int n, Bool hl) { thumb_t *t; unsigned long col; - if (!tns || !win) + if (!tns || !tns->thumbs || !win) return; if (n >= 0 && n < tns->cnt) { @@ -336,7 +385,7 @@ void tns_highlight(tns_t *tns, win_t *win, int n, Bool hl) { int tns_move_selection(tns_t *tns, win_t *win, tnsdir_t dir) { int old; - if (!tns || !win) + if (!tns || !tns->thumbs || !win) return 0; old = tns->sel; @@ -395,7 +444,10 @@ int tns_translate(tns_t *tns, int x, int y) { int n; thumb_t *t; - if (!tns || x < tns->x || y < tns->y) + if (!tns || !tns->thumbs) + return -1; + + if (x < tns->x || y < tns->y) return -1; n = tns->first + (y - tns->y) / thumb_dim * tns->cols + diff --git a/thumbs.h b/thumbs.h index 60e7e7b..4a8af09 100644 --- a/thumbs.h +++ b/thumbs.h @@ -52,6 +52,8 @@ typedef struct { unsigned char dirty; } tns_t; +void tns_clear_cache(tns_t*); + void tns_init(tns_t*, int); void tns_free(tns_t*, win_t*); -- cgit v1.2.3-70-g09d2 From dd9e5dabb155fb9bb06d5a8e5fd6717df1751762 Mon Sep 17 00:00:00 2001 From: Bert Date: Fri, 8 Apr 2011 19:43:27 +0200 Subject: Removed debug output --- thumbs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'thumbs.c') diff --git a/thumbs.c b/thumbs.c index abcfaaa..74ed708 100644 --- a/thumbs.c +++ b/thumbs.c @@ -82,10 +82,8 @@ Imlib_Image* tns_cache_load(const char *filename) { cstats.st_mtim.tv_sec == fstats.st_mtim.tv_sec && cstats.st_mtim.tv_nsec == fstats.st_mtim.tv_nsec) { - printf("cache hit: %s\n", filename); im = imlib_load_image(cfile); - } else - printf("cache MISS: %s\n", filename); + } free(cfile); } @@ -127,7 +125,6 @@ void tns_cache_write(thumb_t *t, Bool force) { TIMESPEC_TO_TIMEVAL(×[0], &fstats.st_atim); TIMESPEC_TO_TIMEVAL(×[1], &fstats.st_mtim); utimes(cfile, times); - printf("thumbnail cache file written: %s\n", t->filename); } } free(cfile); -- cgit v1.2.3-70-g09d2