diff options
Diffstat (limited to 'src/slideshow.c')
-rw-r--r-- | src/slideshow.c | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/src/slideshow.c b/src/slideshow.c new file mode 100644 index 0000000..2ec05a8 --- /dev/null +++ b/src/slideshow.c @@ -0,0 +1,582 @@ +/* slideshow.c + +Copyright (C) 1999-2003 Tom Gilbert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies of the Software and its documentation and acknowledgment shall be +given in the documentation and software packages that this Software was +used. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include "feh.h" +#include "filelist.h" +#include "timers.h" +#include "winwidget.h" +#include "options.h" + +void +init_slideshow_mode(void) +{ + winwidget w = NULL; + int success = 0; + char *s = NULL; + gib_list *l = NULL, *last = NULL; + feh_file *file = NULL; + + D_ENTER(3); + + mode = "slideshow"; + if (opt.start_list_at) + { + l = gib_list_nth(filelist, opt.start_list_at); + opt.start_list_at = 0; /* for next time */ + } + else + { + l = filelist; + } + for (; l; l = l->next) + { + file = FEH_FILE(l->data); + if (last) + { + filelist = feh_file_remove_from_list(filelist, last); + filelist_len--; + last = NULL; + } + current_file = l; + s = slideshow_create_name(file); + 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"); + else 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(); + D_RETURN_(3); +} + +void +cb_slide_timer(void *data) +{ + D_ENTER(4); + slideshow_change_image((winwidget) data, SLIDE_NEXT); + D_RETURN_(4); +} + +void +cb_reload_timer(void *data) +{ + winwidget w = (winwidget) data; + + D_ENTER(4); + feh_reload_image(w, 0, 0); + feh_add_unique_timer(cb_reload_timer, w, opt.reload); + D_RETURN_(4); +} + +void +feh_reload_image(winwidget w, int resize, int force_new) +{ + char *title, *new_title; + int len; + Imlib_Image tmp; + + D_ENTER(4); + + if (!w->file) { + weprintf("couldn't reload, this image has no file associated with it."); + D_RETURN_(4); + } + + free(FEH_FILE(w->file->data)->caption); + FEH_FILE(w->file->data)->caption = NULL; + + len = strlen(w->name) + sizeof("Reloading: ") + 1; + new_title = emalloc(len); + snprintf(new_title, len, "Reloading: %s", w->name); + title = estrdup(w->name); + winwidget_rename(w, new_title); + + + /* force imlib2 not to cache */ + if (force_new) { + winwidget_free_image(w); + } + + /* if the image has changed in dimensions - we gotta resize */ + if ((feh_load_image(&tmp, FEH_FILE(w->file->data))) == 0) { + if (force_new) { + eprintf("failed to reload image\n"); + } else { + weprintf("Couldn't reload image. Is it still there?"); + } + winwidget_rename(w, title); + free(title); + free(new_title); + D_RETURN_(4); + } + if (force_new) { + w->im = tmp; + resize = 1; + winwidget_reset_image(w); + } else { + if ((gib_imlib_image_get_width(w->im) != gib_imlib_image_get_width(tmp)) || (gib_imlib_image_get_height(w->im) != gib_imlib_image_get_height(tmp))) { + resize = 1; + winwidget_reset_image(w); + } + winwidget_free_image(w); + w->im = tmp; + } + + w->mode = MODE_NORMAL; + if ((w->im_w != gib_imlib_image_get_width(w->im)) + || (w->im_h != gib_imlib_image_get_height(w->im))) + w->had_resize = 1; + if (w->has_rotated) + { + Imlib_Image temp; + + temp = gib_imlib_create_rotated_image(w->im, 0.0); + w->im_w = gib_imlib_image_get_width(temp); + w->im_h = gib_imlib_image_get_height(temp); + gib_imlib_free_image_and_decache(temp); + } + else + { + w->im_w = gib_imlib_image_get_width(w->im); + w->im_h = gib_imlib_image_get_height(w->im); + } + winwidget_render_image(w, resize, 1); + + winwidget_rename(w, title); + free(title); + free(new_title); + + D_RETURN_(4); +} + + +void +slideshow_change_image(winwidget winwid, int change) +{ + int success = 0; + gib_list *last = NULL; + int i = 0; + int jmp = 1; + char *s; + + D_ENTER(4); + + /* Without this, clicking a one-image slideshow reloads it. Not very * + intelligent behaviour :-) */ + if (filelist_len < 2) + D_RETURN_(4); + + /* 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 < 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_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); + filelist_len--; + last = NULL; + } + s = slideshow_create_name(FEH_FILE(current_file->data)); + + winwidget_rename(winwid, s); + free(s); + + if ((winwidget_loadimage(winwid, FEH_FILE(current_file->data))) != 0) + { + success = 1; + 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); + winwidget_render_image(winwid, 1, 1); + break; + } + else + last = current_file; + } + if (!success) + { + /* We didn't manage to load any files. Maybe the last one in the show + was deleted? */ + eprintf("No more slides in show"); + } + if (opt.slideshow_delay >= 0.0) + feh_add_timer(cb_slide_timer, winwid, opt.slideshow_delay, + "SLIDE_CHANGE"); + D_RETURN_(4); +} + +void +slideshow_pause_toggle(winwidget w) +{ + char *title, *new_title; + int len; + + if (!opt.paused) + { + opt.paused = 1; + + len = strlen(w->name) + sizeof(" [Paused]") + 1; + new_title = emalloc(len); + snprintf(new_title, len, "%s [Paused]", w->name); + title = estrdup(w->name); + winwidget_rename(w, new_title); + } + else + { + opt.paused = 0; + } +} + +char * +slideshow_create_name(feh_file * file) +{ + char *s = NULL; + int len = 0; + + D_ENTER(4); + if (!opt.title) + { + len = + strlen(PACKAGE " [slideshow mode] - ") + strlen(file->filename) + 1; + s = emalloc(len); + snprintf(s, len, PACKAGE " [%d of %d] - %s", + gib_list_num(filelist, current_file) + 1, + gib_list_length(filelist), file->filename); + } + else + { + s = estrdup(feh_printf(opt.title, file)); + } + + D_RETURN(4, s); +} + +void +feh_action_run(feh_file * file, char *action) +{ + D_ENTER(4); + if (action) + { + D(3, ("Running action %s\n", action)); + char *sys; + sys = feh_printf(action, file); + + if (opt.verbose && !opt.list && !opt.customlist) + fprintf(stderr, "Running action -->%s<--\n", sys); + system(sys); + } + D_RETURN_(4); +} + +char * +feh_printf(char *str, feh_file * file) +{ + char *c; + char buf[20]; + static char ret[4096]; + + D_ENTER(4); + + ret[0] = '\0'; + + for (c = str; *c != '\0'; c++) + { + if (*c == '%') + { + c++; + switch (*c) + { + case 'f': + if (file) + strcat(ret, file->filename); + break; + case 'n': + if (file) + strcat(ret, file->name); + break; + case 'w': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + snprintf(buf, sizeof(buf), "%d", file->info->width); + strcat(ret, buf); + } + break; + case 'h': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + snprintf(buf, sizeof(buf), "%d", file->info->height); + strcat(ret, buf); + } + break; + case 's': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + snprintf(buf, sizeof(buf), "%d", file->info->size); + strcat(ret, buf); + } + break; + case 'p': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + snprintf(buf, sizeof(buf), "%d", file->info->pixels); + strcat(ret, buf); + } + break; + case 't': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + strcat(ret, file->info->format); + } + break; + case 'P': + strcat(ret, PACKAGE); + break; + case 'v': + strcat(ret, VERSION); + break; + case 'm': + strcat(ret, mode); + break; + case 'l': + snprintf(buf, sizeof(buf), "%d", gib_list_length(filelist)); + strcat(ret, buf); + break; + case 'u': + snprintf(buf, sizeof(buf), "%d", + current_file != NULL ? gib_list_num(filelist, + current_file) + + 1 : 0); + strcat(ret, buf); + break; + default: + strncat(ret, c, 1); + break; + } + } + else if (*c == '\\') + { + c++; + switch (*c) + { + case 'n': + strcat(ret, "\n"); + break; + default: + strncat(ret, c, 1); + break; + } + } + else + strncat(ret, c, 1); + } + D_RETURN(4, ret); +} + +void +feh_filelist_image_remove(winwidget winwid, char do_delete) +{ + if (winwid->type == WIN_TYPE_SLIDESHOW) + { + char *s; + gib_list *doomed; + + doomed = current_file; + slideshow_change_image(winwid, SLIDE_NEXT); + filelist_len--; + if (do_delete) + filelist = feh_file_rm_and_free(filelist, doomed); + else + filelist = feh_file_remove_from_list(filelist, doomed); + if (!filelist) + { + /* No more images. Game over ;-) */ + winwidget_destroy(winwid); + return; + } + s = slideshow_create_name(FEH_FILE(winwid->file->data)); + winwidget_rename(winwid, s); + free(s); + } + else if ((winwid->type == WIN_TYPE_SINGLE) + || (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER)) + { + filelist_len--; + if (do_delete) + filelist = feh_file_rm_and_free(filelist, winwid->file); + else + filelist = feh_file_remove_from_list(filelist, winwid->file); + winwidget_destroy(winwid); + } +} + +void slideshow_save_image(winwidget win) +{ + char *tmpname; + + D_ENTER(4); + if(win->file) { + tmpname = feh_unique_filename("", FEH_FILE(win->file->data)->name); + } else if(mode) { + char *tmp; + tmp = estrjoin(".", mode, "png", NULL); + tmpname = feh_unique_filename("", tmp); + free(tmp); + } else { + tmpname = feh_unique_filename("", "noname.png"); + } + + if(!opt.quiet) + printf("saving image to filename '%s'\n", tmpname); + + gib_imlib_save_image(win->im, tmpname); + free(tmpname); + D_RETURN_(4); +} + +gib_list * +feh_list_jump(gib_list * root, gib_list * l, int direction, int num) +{ + int i; + gib_list *ret = NULL; + + if (!root) + return (NULL); + if (!l) + return (root); + + ret = l; + + for (i = 0; i < num; i++) + { + if (direction == FORWARD) + { + if (ret->next) + { + ret = ret->next; + } + else + { + if (opt.cycle_once) + { + exit(0); + } + ret = root; + } + } + else + { + if (ret->prev) + ret = ret->prev; + else + ret = gib_list_last(ret); + } + } + return (ret); +} + |