nsxiv6a0fa25
Slideshow mode is back, in a simplified version
+111 −31
11 files changed
- M Makefile +1 −1
- M README.md +4 −0
- M commands.c +28 −4
- M commands.h +2 −1
- M config.def.h +5 −0
- M image.c +7 −4
- M image.h +6 −0
- M main.c +23 −4
- M options.c +24 −17
- M options.h +1 −0
- M sxiv.1 +10 −0
| @@ -1,4 +1,4 @@ | |||
| 1 | − | VERSION = git-20140103 | |
| 1 | + | VERSION = git-20140104 | |
| 2 | 2 | ||
| 3 | 3 | PREFIX = /usr/local | |
| 4 | 4 | MANPREFIX = $(PREFIX)/share/man | |
| @@ -83,6 +83,7 @@ of small previews is displayed, making it easy to choose an image to open. | |||
| 83 | 83 | -o Write list of marked files to stdout when quitting | |
| 84 | 84 | -q Be quiet, disable warnings | |
| 85 | 85 | -r Search given directories recursively for images | |
| 86 | + | -S DELAY Enable slideshow and set slideshow delay to DELAY seconds | |
| 86 | 87 | -s Scale all images to fit into window | |
| 87 | 88 | -t Start in thumbnail mode | |
| 88 | 89 | -v Print version information and exit | |
| @@ -144,9 +145,12 @@ of small previews is displayed, making it easy to choose an image to open. | |||
| 144 | 145 | ? Rotate image by 180 degrees | |
| 145 | 146 | |,_ Flip image horizontally/vertically | |
| 146 | 147 | ||
| 148 | + | s Toggle slideshow or set delay to [count] seconds | |
| 149 | + | ||
| 147 | 150 | a Toggle anti-aliasing | |
| 148 | 151 | W Resize window to fit image | |
| 149 | 152 | ||
| 153 | + | ||
| 150 | 154 | **Mouse button mappings:** | |
| 151 | 155 | ||
| 152 | 156 | *Image mode:* | |
| @@ -38,6 +38,7 @@ void open_info(void); | |||
| 38 | 38 | void redraw(void); | |
| 39 | 39 | void reset_cursor(void); | |
| 40 | 40 | void animate(void); | |
| 41 | + | void slideshow(void); | |
| 41 | 42 | void set_timeout(timeout_f, int, bool); | |
| 42 | 43 | void reset_timeout(timeout_f); | |
| 43 | 44 | ||
| @@ -79,6 +80,10 @@ bool it_switch_mode(arg_t a) | |||
| 79 | 80 | } | |
| 80 | 81 | img_close(&img, false); | |
| 81 | 82 | reset_timeout(reset_cursor); | |
| 83 | + | if (img.ss.on) { | |
| 84 | + | img.ss.on = false; | |
| 85 | + | reset_timeout(slideshow); | |
| 86 | + | } | |
| 82 | 87 | tns.sel = fileidx; | |
| 83 | 88 | tns.dirty = true; | |
| 84 | 89 | mode = MODE_THUMB; | |
| @@ -475,20 +480,30 @@ bool i_flip(arg_t a) | |||
| 475 | 480 | } | |
| 476 | 481 | } | |
| 477 | 482 | ||
| 478 | − | bool i_toggle_antialias(arg_t a) | |
| 483 | + | bool i_slideshow(arg_t a) | |
| 479 | 484 | { | |
| 480 | 485 | if (mode == MODE_IMAGE) { | |
| 481 | − | img_toggle_antialias(&img); | |
| 486 | + | if (prefix > 0) { | |
| 487 | + | img.ss.on = true; | |
| 488 | + | img.ss.delay = prefix; | |
| 489 | + | set_timeout(slideshow, img.ss.delay * 1000, true); | |
| 490 | + | } else if (img.ss.on) { | |
| 491 | + | img.ss.on = false; | |
| 492 | + | reset_timeout(slideshow); | |
| 493 | + | } else { | |
| 494 | + | img.ss.on = true; | |
| 495 | + | } | |
| 482 | 496 | return true; | |
| 483 | 497 | } else { | |
| 484 | 498 | return false; | |
| 485 | 499 | } | |
| 486 | 500 | } | |
| 487 | 501 | ||
| 488 | − | bool i_change_gamma(arg_t a) | |
| 502 | + | bool i_toggle_antialias(arg_t a) | |
| 489 | 503 | { | |
| 490 | 504 | if (mode == MODE_IMAGE) { | |
| 491 | − | return img_change_gamma(&img, (long) a); | |
| 505 | + | img_toggle_antialias(&img); | |
| 506 | + | return true; | |
| 492 | 507 | } else { | |
| 493 | 508 | return false; | |
| 494 | 509 | } | |
| @@ -504,3 +519,12 @@ bool it_toggle_alpha(arg_t a) | |||
| 504 | 519 | return true; | |
| 505 | 520 | } | |
| 506 | 521 | ||
| 522 | + | bool i_change_gamma(arg_t a) | |
| 523 | + | { | |
| 524 | + | if (mode == MODE_IMAGE) { | |
| 525 | + | return img_change_gamma(&img, (long) a); | |
| 526 | + | } else { | |
| 527 | + | return false; | |
| 528 | + | } | |
| 529 | + | } | |
| 530 | + | ||
| @@ -66,8 +66,9 @@ bool i_fit_to_win(arg_t); | |||
| 66 | 66 | bool i_fit_to_img(arg_t); | |
| 67 | 67 | bool i_rotate(arg_t); | |
| 68 | 68 | bool i_flip(arg_t); | |
| 69 | + | bool i_slideshow(arg_t); | |
| 69 | 70 | bool i_toggle_antialias(arg_t); | |
| 70 | − | bool i_change_gamma(arg_t); | |
| 71 | 71 | bool it_toggle_alpha(arg_t); | |
| 72 | + | bool i_change_gamma(arg_t); | |
| 72 | 73 | ||
| 73 | 74 | #endif /* COMMANDS_H */ | |
| @@ -39,6 +39,9 @@ static const float zoom_levels[] = { | |||
| 39 | 39 | 100.0, 150.0, 200.0, 400.0, 800.0 | |
| 40 | 40 | }; | |
| 41 | 41 | ||
| 42 | + | /* default slideshow delay (in sec, overwritten via -S option): */ | |
| 43 | + | enum { SLIDESHOW_DELAY = 5 }; | |
| 44 | + | ||
| 42 | 45 | /* default settings for multi-frame gif images: */ | |
| 43 | 46 | enum { | |
| 44 | 47 | GIF_DELAY = 100, /* delay time (in ms) */ | |
| @@ -145,6 +148,8 @@ static const keymap_t keys[] = { | |||
| 145 | 148 | { 0, XK_bar, i_flip, (arg_t) FLIP_HORIZONTAL }, | |
| 146 | 149 | { 0, XK_underscore, i_flip, (arg_t) FLIP_VERTICAL }, | |
| 147 | 150 | ||
| 151 | + | { 0, XK_s, i_slideshow, (arg_t) None }, | |
| 152 | + | ||
| 148 | 153 | { 0, XK_a, i_toggle_antialias, (arg_t) None }, | |
| 149 | 154 | { 0, XK_A, it_toggle_alpha, (arg_t) None }, | |
| 150 | 155 | ||
| @@ -83,10 +83,13 @@ void img_init(img_t *img, win_t *win) | |||
| 83 | 83 | img->alpha = !RENDER_WHITE_ALPHA; | |
| 84 | 84 | img->multi.cap = img->multi.cnt = 0; | |
| 85 | 85 | img->multi.animate = false; | |
| 86 | − | img->multi.repeat = 0; | |
| 86 | + | img->multi.length = img->multi.repeat = 0; | |
| 87 | 87 | ||
| 88 | 88 | img->cmod = imlib_create_color_modifier(); | |
| 89 | 89 | img->gamma = MIN(MAX(options->gamma, -GAMMA_RANGE), GAMMA_RANGE); | |
| 90 | + | ||
| 91 | + | img->ss.on = options->slideshow > 0; | |
| 92 | + | img->ss.delay = options->slideshow > 0 ? options->slideshow : SLIDESHOW_DELAY; | |
| 90 | 93 | } | |
| 91 | 94 | ||
| 92 | 95 | void exif_auto_orientate(const fileinfo_t *file) | |
| @@ -143,9 +146,8 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||
| 143 | 146 | img->multi.frames = (img_frame_t*) | |
| 144 | 147 | s_malloc(sizeof(img_frame_t) * img->multi.cap); | |
| 145 | 148 | } | |
| 146 | − | img->multi.cnt = 0; | |
| 147 | − | img->multi.sel = 0; | |
| 148 | − | img->multi.repeat = 0; | |
| 149 | + | img->multi.cnt = img->multi.sel = 0; | |
| 150 | + | img->multi.length = img->multi.repeat = 0; | |
| 149 | 151 | ||
| 150 | 152 | #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 | |
| 151 | 153 | gif = DGifOpenFileName(file->path, NULL); | |
| @@ -275,6 +277,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||
| 275 | 277 | } | |
| 276 | 278 | img->multi.frames[img->multi.cnt].im = im; | |
| 277 | 279 | img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY; | |
| 280 | + | img->multi.length += img->multi.frames[img->multi.cnt].delay; | |
| 278 | 281 | img->multi.cnt++; | |
| 279 | 282 | } | |
| 280 | 283 | } while (rec != TERMINATE_RECORD_TYPE); | |
| @@ -35,6 +35,7 @@ typedef struct { | |||
| 35 | 35 | int cnt; | |
| 36 | 36 | int sel; | |
| 37 | 37 | bool animate; | |
| 38 | + | int length; | |
| 38 | 39 | int repeat; | |
| 39 | 40 | } multi_img_t; | |
| 40 | 41 | ||
| @@ -59,6 +60,11 @@ typedef struct { | |||
| 59 | 60 | Imlib_Color_Modifier cmod; | |
| 60 | 61 | int gamma; | |
| 61 | 62 | ||
| 63 | + | struct { | |
| 64 | + | bool on; | |
| 65 | + | int delay; | |
| 66 | + | } ss; | |
| 67 | + | ||
| 62 | 68 | multi_img_t multi; | |
| 63 | 69 | } img_t; | |
| 64 | 70 | ||
| @@ -68,6 +68,7 @@ typedef struct { | |||
| 68 | 68 | void redraw(void); | |
| 69 | 69 | void reset_cursor(void); | |
| 70 | 70 | void animate(void); | |
| 71 | + | void slideshow(void); | |
| 71 | 72 | void clear_resize(void); | |
| 72 | 73 | ||
| 73 | 74 | appmode_t mode; | |
| @@ -96,9 +97,10 @@ struct { | |||
| 96 | 97 | } info; | |
| 97 | 98 | ||
| 98 | 99 | timeout_t timeouts[] = { | |
| 99 | − | { { 0, 0 }, false, redraw }, | |
| 100 | + | { { 0, 0 }, false, redraw }, | |
| 100 | 101 | { { 0, 0 }, false, reset_cursor }, | |
| 101 | − | { { 0, 0 }, false, animate }, | |
| 102 | + | { { 0, 0 }, false, animate }, | |
| 103 | + | { { 0, 0 }, false, slideshow }, | |
| 102 | 104 | { { 0, 0 }, false, clear_resize }, | |
| 103 | 105 | }; | |
| 104 | 106 | ||
| @@ -304,6 +306,7 @@ void load_image(int new) | |||
| 304 | 306 | return; | |
| 305 | 307 | ||
| 306 | 308 | win_set_cursor(&win, CURSOR_WATCH); | |
| 309 | + | reset_timeout(slideshow); | |
| 307 | 310 | ||
| 308 | 311 | if (new != fileidx) | |
| 309 | 312 | alternate = fileidx; | |
| @@ -363,6 +366,8 @@ void update_info(void) | |||
| 363 | 366 | } | |
| 364 | 367 | } else { | |
| 365 | 368 | n = snprintf(rt, rlen, "%s", mark); | |
| 369 | + | if (img.ss.on) | |
| 370 | + | n += snprintf(rt + n, rlen - n, "%ds | ", img.ss.delay); | |
| 366 | 371 | if (img.gamma != 0) | |
| 367 | 372 | n += snprintf(rt + n, rlen - n, "G%+d | ", img.gamma); | |
| 368 | 373 | n += snprintf(rt + n, rlen - n, "%3d%% | ", (int) (img.zoom * 100.0)); | |
| @@ -389,10 +394,18 @@ void update_info(void) | |||
| 389 | 394 | ||
| 390 | 395 | void redraw(void) | |
| 391 | 396 | { | |
| 392 | − | if (mode == MODE_IMAGE) | |
| 397 | + | int t; | |
| 398 | + | ||
| 399 | + | if (mode == MODE_IMAGE) { | |
| 393 | 400 | img_render(&img); | |
| 394 | − | else | |
| 401 | + | if (img.ss.on) { | |
| 402 | + | t = img.ss.delay * 1000; | |
| 403 | + | t = img.multi.animate ? MAX(t, img.multi.length) : t; | |
| 404 | + | set_timeout(slideshow, t, false); | |
| 405 | + | } | |
| 406 | + | } else { | |
| 395 | 407 | tns_render(&tns); | |
| 408 | + | } | |
| 396 | 409 | update_info(); | |
| 397 | 410 | win_draw(&win); | |
| 398 | 411 | reset_timeout(redraw); | |
| @@ -429,6 +442,12 @@ void animate(void) | |||
| 429 | 442 | } | |
| 430 | 443 | } | |
| 431 | 444 | ||
| 445 | + | void slideshow(void) | |
| 446 | + | { | |
| 447 | + | load_image(fileidx + 1 < filecnt ? fileidx + 1 : 0); | |
| 448 | + | redraw(); | |
| 449 | + | } | |
| 450 | + | ||
| 432 | 451 | void clear_resize(void) | |
| 433 | 452 | { | |
| 434 | 453 | resized = false; | |
| @@ -34,7 +34,7 @@ const options_t *options = (const options_t*) &_options; | |||
| 34 | 34 | void print_usage(void) | |
| 35 | 35 | { | |
| 36 | 36 | printf("usage: sxiv [-bcdFfhioqrstvZ] [-G GAMMA] [-g GEOMETRY] [-n NUM] " | |
| 37 | − | "[-N name] [-z ZOOM] FILES...\n"); | |
| 37 | + | "[-N NAME] [-S DELAY] [-z ZOOM] FILES...\n"); | |
| 38 | 38 | } | |
| 39 | 39 | ||
| 40 | 40 | void print_version(void) | |
| @@ -44,7 +44,7 @@ void print_version(void) | |||
| 44 | 44 | ||
| 45 | 45 | void parse_options(int argc, char **argv) | |
| 46 | 46 | { | |
| 47 | − | int opt, t, gamma; | |
| 47 | + | int n, opt; | |
| 48 | 48 | char *end; | |
| 49 | 49 | ||
| 50 | 50 | _options.from_stdin = false; | |
| @@ -55,6 +55,7 @@ void parse_options(int argc, char **argv) | |||
| 55 | 55 | _options.scalemode = SCALE_MODE; | |
| 56 | 56 | _options.zoom = 1.0; | |
| 57 | 57 | _options.gamma = 0; | |
| 58 | + | _options.slideshow = 0; | |
| 58 | 59 | ||
| 59 | 60 | _options.fixed_win = false; | |
| 60 | 61 | _options.fullscreen = false; | |
| @@ -66,7 +67,7 @@ void parse_options(int argc, char **argv) | |||
| 66 | 67 | _options.thumb_mode = false; | |
| 67 | 68 | _options.clean_cache = false; | |
| 68 | 69 | ||
| 69 | − | while ((opt = getopt(argc, argv, "bcdFfG:g:hin:N:oqrstvZz:")) != -1) { | |
| 70 | + | while ((opt = getopt(argc, argv, "bcdFfG:g:hin:N:oqrS:stvZz:")) != -1) { | |
| 70 | 71 | switch (opt) { | |
| 71 | 72 | case '?': | |
| 72 | 73 | print_usage(); | |
| @@ -87,13 +88,12 @@ void parse_options(int argc, char **argv) | |||
| 87 | 88 | _options.fullscreen = true; | |
| 88 | 89 | break; | |
| 89 | 90 | case 'G': | |
| 90 | − | gamma = strtol(optarg, &end, 0); | |
| 91 | + | n = strtol(optarg, &end, 0); | |
| 91 | 92 | if (*end != '\0') { | |
| 92 | − | fprintf(stderr, "sxiv: invalid argument for option -G: %s\n", | |
| 93 | − | optarg); | |
| 93 | + | fprintf(stderr, "sxiv: invalid argument for option -G: %s\n", optarg); | |
| 94 | 94 | exit(EXIT_FAILURE); | |
| 95 | 95 | } | |
| 96 | − | _options.gamma = gamma; | |
| 96 | + | _options.gamma = n; | |
| 97 | 97 | break; | |
| 98 | 98 | case 'g': | |
| 99 | 99 | _options.geometry = optarg; | |
| @@ -105,13 +105,12 @@ void parse_options(int argc, char **argv) | |||
| 105 | 105 | _options.from_stdin = true; | |
| 106 | 106 | break; | |
| 107 | 107 | case 'n': | |
| 108 | − | if (sscanf(optarg, "%d", &t) <= 0 || t < 1) { | |
| 109 | − | fprintf(stderr, "sxiv: invalid argument for option -n: %s\n", | |
| 110 | − | optarg); | |
| 108 | + | n = strtol(optarg, &end, 0); | |
| 109 | + | if (*end != '\0' || n <= 0) { | |
| 110 | + | fprintf(stderr, "sxiv: invalid argument for option -n: %s\n", optarg); | |
| 111 | 111 | exit(EXIT_FAILURE); | |
| 112 | − | } else { | |
| 113 | − | _options.startnum = t - 1; | |
| 114 | 112 | } | |
| 113 | + | _options.startnum = n - 1; | |
| 115 | 114 | break; | |
| 116 | 115 | case 'N': | |
| 117 | 116 | _options.res_name = optarg; | |
| @@ -125,6 +124,14 @@ void parse_options(int argc, char **argv) | |||
| 125 | 124 | case 'r': | |
| 126 | 125 | _options.recursive = true; | |
| 127 | 126 | break; | |
| 127 | + | case 'S': | |
| 128 | + | n = strtol(optarg, &end, 0); | |
| 129 | + | if (*end != '\0' || n <= 0) { | |
| 130 | + | fprintf(stderr, "sxiv: invalid argument for option -S: %s\n", optarg); | |
| 131 | + | exit(EXIT_FAILURE); | |
| 132 | + | } | |
| 133 | + | _options.slideshow = n; | |
| 134 | + | break; | |
| 128 | 135 | case 's': | |
| 129 | 136 | _options.scalemode = SCALE_FIT; | |
| 130 | 137 | break; | |
| @@ -139,13 +146,13 @@ void parse_options(int argc, char **argv) | |||
| 139 | 146 | _options.zoom = 1.0; | |
| 140 | 147 | break; | |
| 141 | 148 | case 'z': | |
| 142 | − | _options.scalemode = SCALE_ZOOM; | |
| 143 | − | if (sscanf(optarg, "%d", &t) <= 0 || t <= 0) { | |
| 144 | − | fprintf(stderr, "sxiv: invalid argument for option -z: %s\n", | |
| 145 | − | optarg); | |
| 149 | + | n = strtol(optarg, &end, 0); | |
| 150 | + | if (*end != '\n' || n <= 0) { | |
| 151 | + | fprintf(stderr, "sxiv: invalid argument for option -z: %s\n", optarg); | |
| 146 | 152 | exit(EXIT_FAILURE); | |
| 147 | 153 | } | |
| 148 | − | _options.zoom = (float) t / 100.0; | |
| 154 | + | _options.scalemode = SCALE_ZOOM; | |
| 155 | + | _options.zoom = (float) n / 100.0; | |
| 149 | 156 | break; | |
| 150 | 157 | } | |
| 151 | 158 | } | |
| @@ -35,6 +35,7 @@ typedef struct { | |||
| 35 | 35 | scalemode_t scalemode; | |
| 36 | 36 | float zoom; | |
| 37 | 37 | int gamma; | |
| 38 | + | int slideshow; | |
| 38 | 39 | ||
| 39 | 40 | /* window: */ | |
| 40 | 41 | bool fixed_win; | |
| @@ -12,6 +12,8 @@ sxiv \- Simple X Image Viewer | |||
| 12 | 12 | .IR NAME ] | |
| 13 | 13 | .RB [ \-n | |
| 14 | 14 | .IR NUM ] | |
| 15 | + | .RB [ \-S | |
| 16 | + | .IR DELAY ] | |
| 15 | 17 | .RB [ \-z | |
| 16 | 18 | .IR ZOOM ] | |
| 17 | 19 | .IR FILE ... | |
| @@ -78,6 +80,9 @@ Be quiet, disable warnings to standard error stream. | |||
| 78 | 80 | .B \-r | |
| 79 | 81 | Search the given directories recursively for images to view. | |
| 80 | 82 | .TP | |
| 83 | + | .BI "\-S " DELAY | |
| 84 | + | Start in slideshow mode. Set the delay between images to DELAY seconds. | |
| 85 | + | .TP | |
| 81 | 86 | .B \-s | |
| 82 | 87 | Scale all images to fit into window. | |
| 83 | 88 | .TP | |
| @@ -302,6 +307,11 @@ Increase gamma. | |||
| 302 | 307 | Reset gamma. | |
| 303 | 308 | .SS Miscellaneous | |
| 304 | 309 | .TP | |
| 310 | + | .B s | |
| 311 | + | Toggle slideshow mode and/or set the delay between images to | |
| 312 | + | .I count | |
| 313 | + | seconds. | |
| 314 | + | .TP | |
| 305 | 315 | .B a | |
| 306 | 316 | Toggle anti-aliasing. | |
| 307 | 317 | .TP | |