From 1ce11b6307b1c0cc1ab75547fcb5ea63daf72bfe Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Wed, 12 Apr 2017 21:20:34 +0100 Subject: Add generic list container --- test/list.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 test/list.c (limited to 'test') diff --git a/test/list.c b/test/list.c new file mode 100644 index 0000000..8c095d6 --- /dev/null +++ b/test/list.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include "list.h" + +static void test_split_string(void **state) +{ + (void)state; + + struct imv_list *list; + + list = imv_split_string("word", ' '); + assert_true(list); + assert_true(list->len == 1); + assert_false(strcmp(list->items[0], "word")); + imv_list_deep_free(list); + + list = imv_split_string("hello world this is a test", ' '); + assert_true(list); + assert_true(list->len == 6); + assert_false(strcmp(list->items[0], "hello")); + assert_false(strcmp(list->items[1], "world")); + assert_false(strcmp(list->items[2], "this")); + assert_false(strcmp(list->items[3], "is")); + assert_false(strcmp(list->items[4], "a")); + assert_false(strcmp(list->items[5], "test")); + imv_list_deep_free(list); + + list = imv_split_string(" odd whitespace test ", ' '); + assert_true(list); + assert_true(list->len == 3); + assert_false(strcmp(list->items[0], "odd")); + assert_false(strcmp(list->items[1], "whitespace")); + assert_false(strcmp(list->items[2], "test")); + imv_list_deep_free(list); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_split_string), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} + + +/* vim:set ts=2 sts=2 sw=2 et: */ -- cgit v1.2.3 From 5a8932cb21f63af86dffa419ec5da5f4a5d29d70 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 16:49:17 +0100 Subject: Refactor loader to new style --- src/loader.c | 7 +++++-- src/loader.h | 8 ++++---- src/main.c | 18 +++++++++--------- test/loader.c | 15 ++++++++------- 4 files changed, 26 insertions(+), 22 deletions(-) (limited to 'test') diff --git a/src/loader.c b/src/loader.c index d70b66d..c5b64a6 100644 --- a/src/loader.c +++ b/src/loader.c @@ -44,15 +44,17 @@ static int is_thread_cancelled(void) return sigismember(&sigmask, SIGUSR1); } -void imv_init_loader(struct imv_loader *ldr) +struct imv_loader *imv_loader_create(void) { + struct imv_loader *ldr = malloc(sizeof(struct imv_loader)); memset(ldr, 0, sizeof(struct imv_loader)); pthread_mutex_init(&ldr->lock, NULL); /* ignore this signal in case we accidentally receive it */ block_usr1_signal(); + return ldr; } -void imv_destroy_loader(struct imv_loader *ldr) +void imv_loader_free(struct imv_loader *ldr) { /* wait for any existing bg thread to finish */ pthread_join(ldr->bg_thread, NULL); @@ -70,6 +72,7 @@ void imv_destroy_loader(struct imv_loader *ldr) if(ldr->path) { free(ldr->path); } + free(ldr); } void imv_loader_load(struct imv_loader *ldr, const char *path, diff --git a/src/loader.h b/src/loader.h index d2418a2..04dc640 100644 --- a/src/loader.h +++ b/src/loader.h @@ -44,11 +44,11 @@ struct imv_loader { double frame_time; }; -/* Initialises an instance of imv_loader */ -void imv_init_loader(struct imv_loader *img); +/* Creates an instance of imv_loader */ +struct imv_loader *imv_loader_create(void); -/* Cleans up all resources owned by a imv_loader instance */ -void imv_destroy_loader(struct imv_loader *img); +/* Cleans up an imv_loader instance */ +void imv_loader_free(struct imv_loader *ldr); /* Asynchronously load the given file */ void imv_loader_load(struct imv_loader *ldr, const char *path, diff --git a/src/main.c b/src/main.c index 56971c1..e2c0654 100644 --- a/src/main.c +++ b/src/main.c @@ -174,7 +174,7 @@ static void parse_args(int argc, char** argv) struct { struct imv_navigator nav; - struct imv_loader ldr; + struct imv_loader *ldr; struct imv_texture tex; struct imv_viewport view; struct imv_commands *cmds; @@ -354,8 +354,8 @@ int main(int argc, char** argv) fprintf(stderr, "Error loading font: %s\n", TTF_GetError()); } - /* create our main classes on the stack*/ - imv_init_loader(&g_state.ldr); + /* create our main classes */ + g_state.ldr = imv_loader_create(); imv_init_texture(&g_state.tex, g_state.renderer); @@ -506,7 +506,7 @@ int main(int argc, char** argv) } break; case SDLK_PERIOD: - imv_loader_load_next_frame(&g_state.ldr); + imv_loader_load_next_frame(g_state.ldr); break; case SDLK_SPACE: if(!e.key.repeat) { @@ -557,7 +557,7 @@ int main(int argc, char** argv) } /* check if an image failed to load, if so, remove it from our image list */ - char *err_path = imv_loader_get_error(&g_state.ldr); + char *err_path = imv_loader_get_error(g_state.ldr); if(err_path) { imv_navigator_remove(&g_state.nav, err_path); if (strncmp(err_path, "-", 2) == 0) { @@ -593,7 +593,7 @@ int main(int argc, char** argv) scaling_label[g_options.scaling]); imv_viewport_set_title(&g_state.view, title); - imv_loader_load(&g_state.ldr, current_path, stdin_buffer, stdin_buffer_size); + imv_loader_load(g_state.ldr, current_path, stdin_buffer, stdin_buffer_size); g_state.view.playing = 1; } @@ -604,7 +604,7 @@ int main(int argc, char** argv) /* check if a new image is available to display */ FIBITMAP *bmp; int is_new_image; - if(imv_loader_get_image(&g_state.ldr, &bmp, &is_new_image)) { + if(imv_loader_get_image(g_state.ldr, &bmp, &is_new_image)) { imv_texture_set_image(&g_state.tex, bmp); iw = FreeImage_GetWidth(bmp); ih = FreeImage_GetHeight(bmp); @@ -635,7 +635,7 @@ int main(int argc, char** argv) if(dt > 100) { dt = 100; } - imv_loader_time_passed(&g_state.ldr, dt / 1000.0); + imv_loader_time_passed(g_state.ldr, dt / 1000.0); } /* handle slideshow */ @@ -770,7 +770,7 @@ int main(int argc, char** argv) free(g_state.command_buffer); } - imv_destroy_loader(&g_state.ldr); + imv_loader_free(g_state.ldr); imv_destroy_texture(&g_state.tex); imv_navigator_destroy(&g_state.nav); imv_destroy_viewport(&g_state.view); diff --git a/test/loader.c b/test/loader.c index bbbb8d7..e8791c0 100644 --- a/test/loader.c +++ b/test/loader.c @@ -10,24 +10,25 @@ static void test_jpeg_rotation(void **state) { (void)state; - struct imv_loader ldr; + struct imv_loader *ldr = imv_loader_create(); void *retval; char *error; unsigned int width; - imv_init_loader(&ldr); - imv_loader_load(&ldr, "test/orientation.jpg", NULL, 0); - pthread_join(ldr.bg_thread, &retval); + imv_loader_load(ldr, "test/orientation.jpg", NULL, 0); + pthread_join(ldr->bg_thread, &retval); - error = imv_loader_get_error(&ldr); + error = imv_loader_get_error(ldr); assert_false(error); assert_false(retval == PTHREAD_CANCELED); - assert_false(ldr.out_bmp == NULL); + assert_false(ldr->out_bmp == NULL); - width = FreeImage_GetWidth(ldr.out_bmp); + width = FreeImage_GetWidth(ldr->out_bmp); assert_true(width == 1); + + imv_loader_free(ldr); } int main(void) -- cgit v1.2.3 From 4fde6ea289328b5f1668ceb69657e0c4a334b1fb Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 17:10:23 +0100 Subject: Refactor navigator to new style --- src/main.c | 50 ++++++++++++++++++------------------- src/navigator.c | 8 +++--- src/navigator.h | 8 +++--- test/navigator.c | 76 +++++++++++++++++++++++++++----------------------------- 4 files changed, 71 insertions(+), 71 deletions(-) (limited to 'test') diff --git a/src/main.c b/src/main.c index 4006747..adee798 100644 --- a/src/main.c +++ b/src/main.c @@ -173,7 +173,7 @@ static void parse_args(int argc, char** argv) } struct { - struct imv_navigator nav; + struct imv_navigator *nav; struct imv_loader *ldr; struct imv_texture *tex; struct imv_viewport *view; @@ -220,7 +220,7 @@ int main(int argc, char** argv) imv_command_alias(g_state.cmds, "n", "select_rel 1"); imv_command_alias(g_state.cmds, "p", "select_rel -1"); - imv_navigator_init(&g_state.nav); + g_state.nav = imv_navigator_create(); /* parse any command line options given */ parse_args(argc, argv); @@ -249,8 +249,8 @@ int main(int argc, char** argv) buf[--len] = 0; } if(len > 0) { - if(imv_navigator_add(&g_state.nav, buf, g_options.recursive) != 0) { - imv_navigator_destroy(&g_state.nav); + if(imv_navigator_add(g_state.nav, buf, g_options.recursive) != 0) { + imv_navigator_free(g_state.nav); exit(1); } break; @@ -284,25 +284,25 @@ int main(int argc, char** argv) errno = 0; /* clear errno */ } /* add the given path to the list to load */ - if(imv_navigator_add(&g_state.nav, argv[i], g_options.recursive) != 0) { - imv_navigator_destroy(&g_state.nav); + if(imv_navigator_add(g_state.nav, argv[i], g_options.recursive) != 0) { + imv_navigator_free(g_state.nav); exit(1); } } /* if we weren't given any paths we have nothing to view. exit */ - if(!imv_navigator_selection(&g_state.nav)) { + if(!imv_navigator_selection(g_state.nav)) { fprintf(stderr, "No input files. Exiting.\n"); exit(1); } /* go to the chosen starting image if possible */ if(g_options.start_at) { - int start_index = imv_navigator_find_path(&g_state.nav, g_options.start_at); + int start_index = imv_navigator_find_path(g_state.nav, g_options.start_at); if(start_index < 0) { start_index = strtol(g_options.start_at,NULL,10) - 1; } - imv_navigator_select_str(&g_state.nav, start_index); + imv_navigator_select_str(g_state.nav, start_index); } /* we've got something to display, so create an SDL window */ @@ -513,7 +513,7 @@ int main(int argc, char** argv) break; case SDLK_p: if(!e.key.repeat) { - puts(imv_navigator_selection(&g_state.nav)); + puts(imv_navigator_selection(g_state.nav)); } break; case SDLK_d: @@ -557,7 +557,7 @@ int main(int argc, char** argv) /* check if an image failed to load, if so, remove it from our image list */ char *err_path = imv_loader_get_error(g_state.ldr); if(err_path) { - imv_navigator_remove(&g_state.nav, err_path); + imv_navigator_remove(g_state.nav, err_path); if (strncmp(err_path, "-", 2) == 0) { free(stdin_buffer); stdin_buffer_size = 0; @@ -571,13 +571,13 @@ int main(int argc, char** argv) } /* Check if navigator wrapped around paths lists */ - if(!g_options.cycle && imv_navigator_wrapped(&g_state.nav)) { + if(!g_options.cycle && imv_navigator_wrapped(g_state.nav)) { break; } /* if the user has changed image, start loading the new one */ - if(imv_navigator_poll_changed(&g_state.nav, poll_countdown--)) { - const char *current_path = imv_navigator_selection(&g_state.nav); + if(imv_navigator_poll_changed(g_state.nav, poll_countdown--)) { + const char *current_path = imv_navigator_selection(g_state.nav); if(!current_path) { if(g_options.stdin_list) { continue; @@ -587,7 +587,7 @@ int main(int argc, char** argv) } snprintf(title, sizeof(title), "imv - [%i/%i] [LOADING] %s [%s]", - g_state.nav.cur_path + 1, g_state.nav.num_paths, current_path, + g_state.nav->cur_path + 1, g_state.nav->num_paths, current_path, scaling_label[g_options.scaling]); imv_viewport_set_title(g_state.view, title); @@ -643,7 +643,7 @@ int main(int argc, char** argv) g_state.delay_msec += dt; g_state.need_redraw = 1; if(g_state.delay_msec >= g_options.delay) { - imv_navigator_select_rel(&g_state.nav, 1); + imv_navigator_select_rel(g_state.nav, 1); g_state.delay_msec = 0; } } @@ -659,9 +659,9 @@ int main(int argc, char** argv) if(g_state.need_redraw) { /* update window title */ int len; - const char *current_path = imv_navigator_selection(&g_state.nav); + const char *current_path = imv_navigator_selection(g_state.nav); len = snprintf(title, sizeof(title), "imv - [%i/%i] [%ix%i] [%.2f%%] %s [%s]", - g_state.nav.cur_path + 1, g_state.nav.num_paths, g_state.tex->width, g_state.tex->height, + g_state.nav->cur_path + 1, g_state.nav->num_paths, g_state.tex->width, g_state.tex->height, 100.0 * g_state.view->scale, current_path, scaling_label[g_options.scaling]); if(g_options.delay >= 1000) { @@ -744,7 +744,7 @@ int main(int argc, char** argv) buf[--len] = 0; } if(len > 0) { - if(imv_navigator_add(&g_state.nav, buf, g_options.recursive)) { + if(imv_navigator_add(g_state.nav, buf, g_options.recursive)) { break; } g_state.need_redraw = 1; @@ -755,12 +755,12 @@ int main(int argc, char** argv) } } while(g_options.list) { - const char *path = imv_navigator_selection(&g_state.nav); + const char *path = imv_navigator_selection(g_state.nav); if(!path) { break; } fprintf(stdout, "%s\n", path); - imv_navigator_remove(&g_state.nav, path); + imv_navigator_remove(g_state.nav, path); } /* clean up our resources now that we're exiting */ @@ -770,7 +770,7 @@ int main(int argc, char** argv) imv_loader_free(g_state.ldr); imv_texture_free(g_state.tex); - imv_navigator_destroy(&g_state.nav); + imv_navigator_free(g_state.nav); imv_viewport_free(g_state.view); imv_commands_free(g_state.cmds); @@ -813,7 +813,7 @@ void cmd_select_rel(struct imv_list *args) } long int index = strtol(args->items[1], NULL, 10); - imv_navigator_select_rel(&g_state.nav, index); + imv_navigator_select_rel(g_state.nav, index); /* reset slideshow delay */ g_state.delay_msec = 0; @@ -832,8 +832,8 @@ void cmd_zoom(struct imv_list *args) void cmd_remove(struct imv_list *args) { (void)args; - char* path = strdup(imv_navigator_selection(&g_state.nav)); - imv_navigator_remove(&g_state.nav, path); + char* path = strdup(imv_navigator_selection(g_state.nav)); + imv_navigator_remove(g_state.nav, path); free(path); /* reset slideshow delay */ diff --git a/src/navigator.c b/src/navigator.c index 97772cd..6abbfb1 100644 --- a/src/navigator.c +++ b/src/navigator.c @@ -24,13 +24,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include -void imv_navigator_init(struct imv_navigator *nav) +struct imv_navigator *imv_navigator_create(void) { + struct imv_navigator *nav = malloc(sizeof(struct imv_navigator)); memset(nav, 0, sizeof(struct imv_navigator)); nav->last_move_direction = 1; + return nav; } -void imv_navigator_destroy(struct imv_navigator *nav) +void imv_navigator_free(struct imv_navigator *nav) { if(nav->paths) { for(int i = 0; i < nav->num_paths; ++i) { @@ -45,7 +47,7 @@ void imv_navigator_destroy(struct imv_navigator *nav) free(nav->mtimes); } - memset(nav, 0, sizeof(struct imv_navigator)); + free(nav); } static int add_item(struct imv_navigator *nav, const char *path, diff --git a/src/navigator.h b/src/navigator.h index ac3cc59..7b7ccf8 100644 --- a/src/navigator.h +++ b/src/navigator.h @@ -32,11 +32,11 @@ struct imv_navigator { int wrapped; }; -/* Initialises an instance of imv_navigator */ -void imv_navigator_init(struct imv_navigator *nav); +/* Creates an instance of imv_navigator */ +struct imv_navigator *imv_navigator_create(void); -/* Cleans up all resources owned by a imv_navigator instance */ -void imv_navigator_destroy(struct imv_navigator *nav); +/* Cleans up an imv_navigator instance */ +void imv_navigator_free(struct imv_navigator *nav); /* Adds the given path to the navigator's internal list. * If a directory is given, all files within that directory are added. diff --git a/test/navigator.c b/test/navigator.c index 55ab392..2aba317 100644 --- a/test/navigator.c +++ b/test/navigator.c @@ -19,78 +19,76 @@ static void test_navigator_add_remove(void **state) { (void)state; - struct imv_navigator nav; - imv_navigator_init(&nav); + struct imv_navigator *nav = imv_navigator_create(); /* Check poll_changed */ - assert_false(imv_navigator_poll_changed(&nav, 0)); + assert_false(imv_navigator_poll_changed(nav, 0)); /* Add 6 paths, one non-existant should fail */ - assert_false(imv_navigator_add(&nav, FILENAME1, 0)); - assert_false(imv_navigator_add(&nav, FILENAME2, 0)); - assert_false(imv_navigator_add(&nav, FILENAME3, 0)); - assert_false(imv_navigator_add(&nav, FILENAME4, 0)); - assert_false(imv_navigator_add(&nav, FILENAME5, 0)); - assert_false(imv_navigator_add(&nav, FILENAME6, 0)); - assert_int_equal(nav.num_paths, 6); + assert_false(imv_navigator_add(nav, FILENAME1, 0)); + assert_false(imv_navigator_add(nav, FILENAME2, 0)); + assert_false(imv_navigator_add(nav, FILENAME3, 0)); + assert_false(imv_navigator_add(nav, FILENAME4, 0)); + assert_false(imv_navigator_add(nav, FILENAME5, 0)); + assert_false(imv_navigator_add(nav, FILENAME6, 0)); + assert_int_equal(nav->num_paths, 6); /* Check poll_changed */ - assert_true(imv_navigator_poll_changed(&nav, 0)); + assert_true(imv_navigator_poll_changed(nav, 0)); /* Make sure current selection is #1 */ - assert_string_equal(imv_navigator_selection(&nav), FILENAME1); + assert_string_equal(imv_navigator_selection(nav), FILENAME1); /* Move right and remove current file (#2); should get to #3 */ - imv_navigator_select_rel(&nav, 1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME2); - imv_navigator_remove(&nav, FILENAME2); - assert_int_equal(nav.num_paths, 5); - assert_string_equal(imv_navigator_selection(&nav), FILENAME3); + imv_navigator_select_rel(nav, 1); + assert_string_equal(imv_navigator_selection(nav), FILENAME2); + imv_navigator_remove(nav, FILENAME2); + assert_int_equal(nav->num_paths, 5); + assert_string_equal(imv_navigator_selection(nav), FILENAME3); /* Move left and remove current file (#1); should get to #6 */ - imv_navigator_select_rel(&nav, -1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME1); - imv_navigator_remove(&nav, FILENAME1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME6); + imv_navigator_select_rel(nav, -1); + assert_string_equal(imv_navigator_selection(nav), FILENAME1); + imv_navigator_remove(nav, FILENAME1); + assert_string_equal(imv_navigator_selection(nav), FILENAME6); /* Move left, right, remove current file (#6); should get to #3 */ - imv_navigator_select_rel(&nav, -1); - imv_navigator_select_rel(&nav, 1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME6); - imv_navigator_remove(&nav, FILENAME6); - assert_string_equal(imv_navigator_selection(&nav), FILENAME3); + imv_navigator_select_rel(nav, -1); + imv_navigator_select_rel(nav, 1); + assert_string_equal(imv_navigator_selection(nav), FILENAME6); + imv_navigator_remove(nav, FILENAME6); + assert_string_equal(imv_navigator_selection(nav), FILENAME3); /* Remove #4; should not move */ - imv_navigator_remove(&nav, FILENAME4); - assert_string_equal(imv_navigator_selection(&nav), FILENAME3); + imv_navigator_remove(nav, FILENAME4); + assert_string_equal(imv_navigator_selection(nav), FILENAME3); /* Verify that #4 is removed by moving left; should get to #5 */ - imv_navigator_select_rel(&nav, 1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME5); + imv_navigator_select_rel(nav, 1); + assert_string_equal(imv_navigator_selection(nav), FILENAME5); - imv_navigator_destroy(&nav); + imv_navigator_free(nav); } static void test_navigator_file_changed(void **state) { int fd; - struct imv_navigator nav; + struct imv_navigator *nav = imv_navigator_create(); struct timespec times[2] = { {0, 0}, {0, 0} }; (void)state; - imv_navigator_init(&nav); fd = open(FILENAME1, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd == -1) { - imv_navigator_destroy(&nav); + imv_navigator_free(nav); (void)unlink(FILENAME1); skip(); } assert_false(futimens(fd, times) == -1); - assert_false(imv_navigator_add(&nav, FILENAME1, 0)); - assert_true(imv_navigator_poll_changed(&nav, 0)); - assert_false(imv_navigator_poll_changed(&nav, 0)); + assert_false(imv_navigator_add(nav, FILENAME1, 0)); + assert_true(imv_navigator_poll_changed(nav, 0)); + assert_false(imv_navigator_poll_changed(nav, 0)); assert_false(sleep(1)); @@ -103,11 +101,11 @@ static void test_navigator_file_changed(void **state) times[1].tv_sec = UTIME_NOW; assert_false(futimens(fd, times) == -1); - assert_true(imv_navigator_poll_changed(&nav, 0)); + assert_true(imv_navigator_poll_changed(nav, 0)); (void)close(fd); (void)unlink(FILENAME1); - imv_navigator_destroy(&nav); + imv_navigator_free(nav); } int main(void) -- cgit v1.2.3 From f085f13f429d01a8f72e3b348a694124d5ba7533 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 22:34:14 +0100 Subject: Refactor navigator poll rate limiting --- src/main.c | 8 +------- src/navigator.c | 18 +++++++++++++++--- src/navigator.h | 4 +++- test/navigator.c | 13 ++++++++----- 4 files changed, 27 insertions(+), 16 deletions(-) (limited to 'test') diff --git a/src/main.c b/src/main.c index 0d7688e..4bdfe50 100644 --- a/src/main.c +++ b/src/main.c @@ -370,9 +370,6 @@ int main(int argc, char** argv) unsigned int last_time = SDL_GetTicks(); unsigned int current_time; - /* keep file change polling rate under control */ - static uint8_t poll_countdown = UINT8_MAX; - g_state.need_redraw = 1; g_state.need_rescale = 0; @@ -422,7 +419,7 @@ int main(int argc, char** argv) } /* if the user has changed image, start loading the new one */ - if(imv_navigator_poll_changed(g_state.nav, poll_countdown--)) { + if(imv_navigator_poll_changed(g_state.nav)) { const char *current_path = imv_navigator_selection(g_state.nav); if(!current_path) { if(g_options.stdin_list) { @@ -560,9 +557,6 @@ int main(int argc, char** argv) /* redraw complete, unset the flag */ g_state.need_redraw = 0; - /* reset poll countdown timer */ - poll_countdown = UINT8_MAX; - /* tell SDL to show the newly drawn frame */ SDL_RenderPresent(g_state.renderer); } diff --git a/src/navigator.c b/src/navigator.c index 6abbfb1..ae7bccd 100644 --- a/src/navigator.c +++ b/src/navigator.c @@ -47,6 +47,10 @@ void imv_navigator_free(struct imv_navigator *nav) free(nav->mtimes); } + if(nav->ctimes) { + free(nav->ctimes); + } + free(nav); } @@ -56,19 +60,23 @@ static int add_item(struct imv_navigator *nav, const char *path, if(nav->num_paths % BUFFER_SIZE == 0) { char **new_paths; time_t *new_mtimes; + time_t *new_ctimes; size_t new_size = nav->num_paths + BUFFER_SIZE; new_paths = realloc(nav->paths, sizeof(char*) * new_size); new_mtimes = realloc(nav->mtimes, sizeof(time_t) * new_size); - if (new_paths == NULL || new_mtimes == NULL) { + new_ctimes = realloc(nav->ctimes, sizeof(time_t) * new_size); + if (new_paths == NULL || new_mtimes == NULL || new_ctimes == NULL) { return 1; } nav->paths = new_paths; nav->mtimes = new_mtimes; + nav->ctimes = new_ctimes; } if((nav->paths[nav->num_paths] = strndup(path, PATH_MAX)) == NULL) { return 1; } nav->mtimes[nav->num_paths] = mtime; + nav->ctimes[nav->num_paths] = time(NULL); nav->num_paths += 1; if(nav->num_paths == 1) { nav->changed = 1; @@ -218,7 +226,7 @@ int imv_navigator_find_path(struct imv_navigator *nav, const char *path) return -1; } -int imv_navigator_poll_changed(struct imv_navigator *nav, const int nopoll) +int imv_navigator_poll_changed(struct imv_navigator *nav) { if(nav->changed) { nav->changed = 0; @@ -229,7 +237,11 @@ int imv_navigator_poll_changed(struct imv_navigator *nav, const int nopoll) return 0; }; - if(!nopoll) { + time_t cur_time = time(NULL); + /* limit polling to once per second */ + if(nav->ctimes[nav->cur_path] < cur_time - 1) { + nav->ctimes[nav->cur_path] = cur_time; + struct stat file_info; if(stat(nav->paths[nav->cur_path], &file_info) == -1) { return 0; diff --git a/src/navigator.h b/src/navigator.h index 7b7ccf8..0d56fa7 100644 --- a/src/navigator.h +++ b/src/navigator.h @@ -27,9 +27,11 @@ struct imv_navigator { int cur_path; char **paths; time_t *mtimes; + time_t *ctimes; int last_move_direction; int changed; int wrapped; + int poll_countdown; }; /* Creates an instance of imv_navigator */ @@ -65,7 +67,7 @@ int imv_navigator_find_path(struct imv_navigator *nav, const char *path); /* Returns 1 if either the currently selected path or underlying file has * changed since last called */ -int imv_navigator_poll_changed(struct imv_navigator *nav, const int nopoll); +int imv_navigator_poll_changed(struct imv_navigator *nav); /* Check whether navigator wrapped around paths list */ int imv_navigator_wrapped(struct imv_navigator *nav); diff --git a/test/navigator.c b/test/navigator.c index 2aba317..3f2c50f 100644 --- a/test/navigator.c +++ b/test/navigator.c @@ -22,7 +22,7 @@ static void test_navigator_add_remove(void **state) struct imv_navigator *nav = imv_navigator_create(); /* Check poll_changed */ - assert_false(imv_navigator_poll_changed(nav, 0)); + assert_false(imv_navigator_poll_changed(nav)); /* Add 6 paths, one non-existant should fail */ assert_false(imv_navigator_add(nav, FILENAME1, 0)); @@ -34,7 +34,7 @@ static void test_navigator_add_remove(void **state) assert_int_equal(nav->num_paths, 6); /* Check poll_changed */ - assert_true(imv_navigator_poll_changed(nav, 0)); + assert_true(imv_navigator_poll_changed(nav)); /* Make sure current selection is #1 */ assert_string_equal(imv_navigator_selection(nav), FILENAME1); @@ -87,8 +87,8 @@ static void test_navigator_file_changed(void **state) assert_false(futimens(fd, times) == -1); assert_false(imv_navigator_add(nav, FILENAME1, 0)); - assert_true(imv_navigator_poll_changed(nav, 0)); - assert_false(imv_navigator_poll_changed(nav, 0)); + assert_true(imv_navigator_poll_changed(nav)); + assert_false(imv_navigator_poll_changed(nav)); assert_false(sleep(1)); @@ -101,7 +101,10 @@ static void test_navigator_file_changed(void **state) times[1].tv_sec = UTIME_NOW; assert_false(futimens(fd, times) == -1); - assert_true(imv_navigator_poll_changed(nav, 0)); + /* sleep to ensure we don't hit the poll rate-limiting */ + sleep(1); + + assert_true(imv_navigator_poll_changed(nav)); (void)close(fd); (void)unlink(FILENAME1); -- cgit v1.2.3