void feh_add_unique_timer(void (*func) (void *data), void *data, double in) { static long i = 0; char evname[20]; snprintf(evname, sizeof(evname), "T_%ld", i); D(("adding timer with unique name %s\n", evname)); feh_add_timer(func, data, in, evname); i++; /* Mega paranoia ;) */ if (i > 1000000) i = 0; return; }
void init_slideshow_mode(void) { winwidget w = NULL; int success = 0; char *s = NULL; gib_list *l = filelist, *last = NULL; feh_file *file = NULL; for (; l && opt.start_list_at; l = l->next) { if (!strcmp(opt.start_list_at, FEH_FILE(l->data)->filename)) { opt.start_list_at = NULL; break; } } if (opt.start_list_at) eprintf("--start-at %s: File not found in filelist", opt.start_list_at); mode = "slideshow"; for (; l; l = l->next) { file = FEH_FILE(l->data); if (last) { filelist = feh_file_remove_from_list(filelist, last); last = NULL; } current_file = l; s = slideshow_create_name(file, NULL); if ((w = winwidget_create_from_file(l, s, WIN_TYPE_SLIDESHOW)) != NULL) { free(s); success = 1; winwidget_show(w); if (opt.slideshow_delay > 0.0) feh_add_timer(cb_slide_timer, w, opt.slideshow_delay, "SLIDE_CHANGE"); if (opt.reload > 0) feh_add_unique_timer(cb_reload_timer, w, opt.reload); break; } else { free(s); last = l; } } if (!success) show_mini_usage(); return; }
void slideshow_change_image(winwidget winwid, int change, int render) { gib_list *last = NULL; int i = 0; int jmp = 1; /* We can't use filelist_len in the for loop, since that changes when we * encounter invalid images. */ int our_filelist_len = filelist_len; char *s; unsigned char tmode =0; int tim_x =0; int tim_y =0; double tzoom =0; /* Without this, clicking a one-image slideshow reloads it. Not very * intelligent behaviour :-) */ if (filelist_len < 2 && opt.cycle_once == 0) return; /* Ok. I do this in such an odd way to ensure that if the last or first * image is not loadable, it will go through in the right direction to * find the correct one. Otherwise SLIDE_LAST would try the last file, * then loop forward to find a loadable one. */ if (change == SLIDE_FIRST) { current_file = gib_list_last(filelist); change = SLIDE_NEXT; } else if (change == SLIDE_LAST) { current_file = filelist; change = SLIDE_PREV; } /* The for loop prevents us looping infinitely */ for (i = 0; i < our_filelist_len; i++) { winwidget_free_image(winwid); switch (change) { case SLIDE_NEXT: current_file = feh_list_jump(filelist, current_file, FORWARD, 1); break; case SLIDE_PREV: current_file = feh_list_jump(filelist, current_file, BACK, 1); break; case SLIDE_RAND: if (filelist_len > 1) { current_file = feh_list_jump(filelist, current_file, FORWARD, (rand() % (filelist_len - 1)) + 1); change = SLIDE_NEXT; } break; case SLIDE_JUMP_FWD: if (filelist_len < 5) jmp = 1; else if (filelist_len < 40) jmp = 2; else jmp = filelist_len / 20; if (!jmp) jmp = 2; current_file = feh_list_jump(filelist, current_file, FORWARD, jmp); /* important. if the load fails, we only want to step on ONCE to try the next file, not another jmp */ change = SLIDE_NEXT; break; case SLIDE_JUMP_BACK: if (filelist_len < 5) jmp = 1; else if (filelist_len < 40) jmp = 2; else jmp = filelist_len / 20; if (!jmp) jmp = 2; current_file = feh_list_jump(filelist, current_file, BACK, jmp); /* important. if the load fails, we only want to step back ONCE to try the previous file, not another jmp */ change = SLIDE_NEXT; break; default: eprintf("BUG!\n"); break; } if (last) { filelist = feh_file_remove_from_list(filelist, last); last = NULL; } if (opt.keep_zoom_vp) { /* pre loadimage - record settings */ tmode = winwid->mode; tim_x = winwid->im_x; tim_y = winwid->im_y; tzoom = winwid->zoom; } if ((winwidget_loadimage(winwid, FEH_FILE(current_file->data))) != 0) { winwid->mode = MODE_NORMAL; winwid->file = current_file; if ((winwid->im_w != gib_imlib_image_get_width(winwid->im)) || (winwid->im_h != gib_imlib_image_get_height(winwid->im))) winwid->had_resize = 1; winwidget_reset_image(winwid); winwid->im_w = gib_imlib_image_get_width(winwid->im); winwid->im_h = gib_imlib_image_get_height(winwid->im); if (opt.keep_zoom_vp) { /* put back in: */ winwid->mode = tmode; winwid->im_x = tim_x; winwid->im_y = tim_y; winwid->zoom = tzoom; } if (render) { if (opt.keep_zoom_vp) { winwidget_render_image(winwid, 0, 0); } else { winwidget_render_image(winwid, 1, 0); } } s = slideshow_create_name(FEH_FILE(current_file->data), winwid); winwidget_rename(winwid, s); free(s); break; } else last = current_file; } if (last) filelist = feh_file_remove_from_list(filelist, last); if (filelist_len == 0) eprintf("No more slides in show"); if (opt.slideshow_delay > 0.0) feh_add_timer(cb_slide_timer, winwid, opt.slideshow_delay, "SLIDE_CHANGE"); return; }
void init_slideshow_mode(void) { winwidget w = NULL; int success = 0; gib_list *l = filelist, *last = NULL; /* * In theory, --start-at FILENAME is simple: Look for a file called * FILENAME, start the filelist there, done. * * In practice, there are cases where this isn't sufficient. For instance, * a user running 'feh --start-at hello.jpg /tmp' will expect feh to start * at /tmp/hello.jpg, as if they had used * 'feh --start-at /tmp/hello.jpg /tmp'. Similarly, XDG Desktop files * may lead to the invocation 'feh --start-at /tmp/hello.jpg .' in /tmp, * expecting the behaviour of 'feh --start-at ./hello.jpg .'. * * Since a good user experience is not about being technically correct, but * about delivering the expected behaviour, we do some fuzzy matching * here. In the worst case, this will cause --start-at to start at the * wrong file. */ // Try finding an exact filename match first for (; l && opt.start_list_at; l = l->next) { if (!strcmp(opt.start_list_at, FEH_FILE(l->data)->filename)) { opt.start_list_at = NULL; break; } } /* * If it didn't work (opt.start_list_at is still set): Fall back to * comparing just the filenames without directory prefixes. This may lead * to false positives, but for now that's just the way it is. */ if (opt.start_list_at) { char *current_filename; char *start_at_filename = strrchr(opt.start_list_at, '/'); if (start_at_filename) { start_at_filename++; // We only care about the part after the '/' } else { start_at_filename = opt.start_list_at; } for (l = filelist; l && opt.start_list_at; l = l->next) { current_filename = strrchr(FEH_FILE(l->data)->filename, '/'); if (current_filename) { current_filename++; // We only care about the part after the '/' } else { current_filename = FEH_FILE(l->data)->filename; } if (!strcmp(start_at_filename, current_filename)) { opt.start_list_at = NULL; break; } } } // If that didn't work either, we're out of luck. if (opt.start_list_at) eprintf("--start-at %s: File not found in filelist", opt.start_list_at); if (!opt.title) opt.title = PACKAGE " [%u of %l] - %f"; mode = "slideshow"; for (; l; l = l->next) { if (last) { filelist = feh_file_remove_from_list(filelist, last); last = NULL; } current_file = l; if ((w = winwidget_create_from_file(l, WIN_TYPE_SLIDESHOW)) != NULL) { success = 1; winwidget_show(w); if (opt.slideshow_delay > 0.0) feh_add_timer(cb_slide_timer, w, opt.slideshow_delay, "SLIDE_CHANGE"); if (opt.reload > 0) feh_add_unique_timer(cb_reload_timer, w, opt.reload); break; } else { last = l; } } if (!success) show_mini_usage(); return; }
void slideshow_change_image(winwidget winwid, int change, int render) { gib_list *last = NULL; gib_list *previous_file = current_file; int i = 0; int jmp = 1; /* We can't use filelist_len in the for loop, since that changes when we * encounter invalid images. */ int our_filelist_len = filelist_len; if (opt.slideshow_delay > 0.0) feh_add_timer(cb_slide_timer, winwid, opt.slideshow_delay, "SLIDE_CHANGE"); /* Without this, clicking a one-image slideshow reloads it. Not very * intelligent behaviour :-) */ if (filelist_len < 2 && opt.on_last_slide != ON_LAST_SLIDE_QUIT) return; /* Ok. I do this in such an odd way to ensure that if the last or first * image is not loadable, it will go through in the right direction to * find the correct one. Otherwise SLIDE_LAST would try the last file, * then loop forward to find a loadable one. */ if (change == SLIDE_FIRST) { current_file = gib_list_last(filelist); change = SLIDE_NEXT; previous_file = NULL; } else if (change == SLIDE_LAST) { current_file = filelist; change = SLIDE_PREV; previous_file = NULL; } /* The for loop prevents us looping infinitely */ for (i = 0; i < our_filelist_len; i++) { winwidget_free_image(winwid); switch (change) { case SLIDE_NEXT: current_file = feh_list_jump(filelist, current_file, FORWARD, 1); break; case SLIDE_PREV: current_file = feh_list_jump(filelist, current_file, BACK, 1); break; case SLIDE_RAND: if (filelist_len > 1) { current_file = feh_list_jump(filelist, current_file, FORWARD, (random() % (filelist_len - 1)) + 1); change = SLIDE_NEXT; } break; case SLIDE_JUMP_FWD: if (filelist_len < 5) jmp = 1; else if (filelist_len < 40) jmp = 2; else jmp = filelist_len / 20; if (!jmp) jmp = 2; current_file = feh_list_jump(filelist, current_file, FORWARD, jmp); /* important. if the load fails, we only want to step on ONCE to try the next file, not another jmp */ change = SLIDE_NEXT; break; case SLIDE_JUMP_BACK: if (filelist_len < 5) jmp = 1; else if (filelist_len < 40) jmp = 2; else jmp = filelist_len / 20; if (!jmp) jmp = 2; current_file = feh_list_jump(filelist, current_file, BACK, jmp); /* important. if the load fails, we only want to step back ONCE to try the previous file, not another jmp */ change = SLIDE_NEXT; break; case SLIDE_JUMP_NEXT_DIR: { char old_dir[PATH_MAX], new_dir[PATH_MAX]; int j; feh_file_dirname(old_dir, FEH_FILE(current_file->data), PATH_MAX); for (j = 0; j < our_filelist_len; j++) { current_file = feh_list_jump(filelist, current_file, FORWARD, 1); feh_file_dirname(new_dir, FEH_FILE(current_file->data), PATH_MAX); if (strcmp(old_dir, new_dir) != 0) break; } } change = SLIDE_NEXT; break; case SLIDE_JUMP_PREV_DIR: { char old_dir[PATH_MAX], new_dir[PATH_MAX]; int j; /* Start the search from the previous file in case we are on the first file of a directory */ current_file = feh_list_jump(filelist, current_file, BACK, 1); feh_file_dirname(old_dir, FEH_FILE(current_file->data), PATH_MAX); for (j = 0; j < our_filelist_len; j++) { current_file = feh_list_jump(filelist, current_file, BACK, 1); feh_file_dirname(new_dir, FEH_FILE(current_file->data), PATH_MAX); if (strcmp(old_dir, new_dir) != 0) break; } /* Next file is the first entry of prev_dir */ current_file = feh_list_jump(filelist, current_file, FORWARD, 1); } change = SLIDE_NEXT; break; default: eprintf("BUG!\n"); break; } if (last) { filelist = feh_file_remove_from_list(filelist, last); last = NULL; } if (opt.on_last_slide == ON_LAST_SLIDE_HOLD && previous_file && ((current_file == filelist && change == SLIDE_NEXT) || (previous_file == filelist && change == SLIDE_PREV))) { current_file = previous_file; } if (winwidget_loadimage(winwid, FEH_FILE(current_file->data))) { int w = gib_imlib_image_get_width(winwid->im); int h = gib_imlib_image_get_height(winwid->im); if (feh_should_ignore_image(winwid->im)) { last = current_file; continue; } winwid->mode = MODE_NORMAL; winwid->file = current_file; if ((winwid->im_w != w) || (winwid->im_h != h)) winwid->had_resize = 1; winwidget_reset_image(winwid); winwid->im_w = w; winwid->im_h = h; if (render) { winwidget_render_image(winwid, 1, 0); } break; } else last = current_file; } if (last) filelist = feh_file_remove_from_list(filelist, last); if (filelist_len == 0) eprintf("No more slides in show"); return; }