@@ -1,4 +1,4 @@ | |||||
VERSION = git-20140103 | VERSION = git-20140104 | ||||
PREFIX = /usr/local | PREFIX = /usr/local | ||||
MANPREFIX = $(PREFIX)/share/man | MANPREFIX = $(PREFIX)/share/man | ||||
@@ -83,6 +83,7 @@ of small previews is displayed, making it easy to choose an image to open. | |||||
-o Write list of marked files to stdout when quitting | -o Write list of marked files to stdout when quitting | ||||
-q Be quiet, disable warnings | -q Be quiet, disable warnings | ||||
-r Search given directories recursively for images | -r Search given directories recursively for images | ||||
-S DELAY Enable slideshow and set slideshow delay to DELAY seconds | |||||
-s Scale all images to fit into window | -s Scale all images to fit into window | ||||
-t Start in thumbnail mode | -t Start in thumbnail mode | ||||
-v Print version information and exit | -v Print version information and exit | ||||
@@ -144,9 +145,12 @@ of small previews is displayed, making it easy to choose an image to open. | |||||
? Rotate image by 180 degrees | ? Rotate image by 180 degrees | ||||
|,_ Flip image horizontally/vertically | |,_ Flip image horizontally/vertically | ||||
s Toggle slideshow or set delay to [count] seconds | |||||
a Toggle anti-aliasing | a Toggle anti-aliasing | ||||
W Resize window to fit image | W Resize window to fit image | ||||
**Mouse button mappings:** | **Mouse button mappings:** | ||||
*Image mode:* | *Image mode:* | ||||
@@ -38,6 +38,7 @@ void open_info(void); | |||||
void redraw(void); | void redraw(void); | ||||
void reset_cursor(void); | void reset_cursor(void); | ||||
void animate(void); | void animate(void); | ||||
void slideshow(void); | |||||
void set_timeout(timeout_f, int, bool); | void set_timeout(timeout_f, int, bool); | ||||
void reset_timeout(timeout_f); | void reset_timeout(timeout_f); | ||||
@@ -79,6 +80,10 @@ bool it_switch_mode(arg_t a) | |||||
} | } | ||||
img_close(&img, false); | img_close(&img, false); | ||||
reset_timeout(reset_cursor); | reset_timeout(reset_cursor); | ||||
if (img.ss.on) { | |||||
img.ss.on = false; | |||||
reset_timeout(slideshow); | |||||
} | |||||
tns.sel = fileidx; | tns.sel = fileidx; | ||||
tns.dirty = true; | tns.dirty = true; | ||||
mode = MODE_THUMB; | mode = MODE_THUMB; | ||||
@@ -475,20 +480,30 @@ bool i_flip(arg_t a) | |||||
} | } | ||||
} | } | ||||
bool i_toggle_antialias(arg_t a) | bool i_slideshow(arg_t a) | ||||
{ | { | ||||
if (mode == MODE_IMAGE) { | if (mode == MODE_IMAGE) { | ||||
img_toggle_antialias(&img); | if (prefix > 0) { | ||||
img.ss.on = true; | |||||
img.ss.delay = prefix; | |||||
set_timeout(slideshow, img.ss.delay * 1000, true); | |||||
} else if (img.ss.on) { | |||||
img.ss.on = false; | |||||
reset_timeout(slideshow); | |||||
} else { | |||||
img.ss.on = true; | |||||
} | |||||
return true; | return true; | ||||
} else { | } else { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
bool i_change_gamma(arg_t a) | bool i_toggle_antialias(arg_t a) | ||||
{ | { | ||||
if (mode == MODE_IMAGE) { | if (mode == MODE_IMAGE) { | ||||
return img_change_gamma(&img, (long) a); | img_toggle_antialias(&img); | ||||
return true; | |||||
} else { | } else { | ||||
return false; | return false; | ||||
} | } | ||||
@@ -504,3 +519,12 @@ bool it_toggle_alpha(arg_t a) | |||||
return true; | return true; | ||||
} | } | ||||
bool i_change_gamma(arg_t a) | |||||
{ | |||||
if (mode == MODE_IMAGE) { | |||||
return img_change_gamma(&img, (long) a); | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
@@ -66,8 +66,9 @@ bool i_fit_to_win(arg_t); | |||||
bool i_fit_to_img(arg_t); | bool i_fit_to_img(arg_t); | ||||
bool i_rotate(arg_t); | bool i_rotate(arg_t); | ||||
bool i_flip(arg_t); | bool i_flip(arg_t); | ||||
bool i_slideshow(arg_t); | |||||
bool i_toggle_antialias(arg_t); | bool i_toggle_antialias(arg_t); | ||||
bool i_change_gamma(arg_t); | |||||
bool it_toggle_alpha(arg_t); | bool it_toggle_alpha(arg_t); | ||||
bool i_change_gamma(arg_t); | |||||
#endif /* COMMANDS_H */ | #endif /* COMMANDS_H */ |
@@ -39,6 +39,9 @@ static const float zoom_levels[] = { | |||||
100.0, 150.0, 200.0, 400.0, 800.0 | 100.0, 150.0, 200.0, 400.0, 800.0 | ||||
}; | }; | ||||
/* default slideshow delay (in sec, overwritten via -S option): */ | |||||
enum { SLIDESHOW_DELAY = 5 }; | |||||
/* default settings for multi-frame gif images: */ | /* default settings for multi-frame gif images: */ | ||||
enum { | enum { | ||||
GIF_DELAY = 100, /* delay time (in ms) */ | GIF_DELAY = 100, /* delay time (in ms) */ | ||||
@@ -145,6 +148,8 @@ static const keymap_t keys[] = { | |||||
{ 0, XK_bar, i_flip, (arg_t) FLIP_HORIZONTAL }, | { 0, XK_bar, i_flip, (arg_t) FLIP_HORIZONTAL }, | ||||
{ 0, XK_underscore, i_flip, (arg_t) FLIP_VERTICAL }, | { 0, XK_underscore, i_flip, (arg_t) FLIP_VERTICAL }, | ||||
{ 0, XK_s, i_slideshow, (arg_t) None }, | |||||
{ 0, XK_a, i_toggle_antialias, (arg_t) None }, | { 0, XK_a, i_toggle_antialias, (arg_t) None }, | ||||
{ 0, XK_A, it_toggle_alpha, (arg_t) None }, | { 0, XK_A, it_toggle_alpha, (arg_t) None }, | ||||
@@ -83,10 +83,13 @@ void img_init(img_t *img, win_t *win) | |||||
img->alpha = !RENDER_WHITE_ALPHA; | img->alpha = !RENDER_WHITE_ALPHA; | ||||
img->multi.cap = img->multi.cnt = 0; | img->multi.cap = img->multi.cnt = 0; | ||||
img->multi.animate = false; | img->multi.animate = false; | ||||
img->multi.repeat = 0; | img->multi.length = img->multi.repeat = 0; | ||||
img->cmod = imlib_create_color_modifier(); | img->cmod = imlib_create_color_modifier(); | ||||
img->gamma = MIN(MAX(options->gamma, -GAMMA_RANGE), GAMMA_RANGE); | img->gamma = MIN(MAX(options->gamma, -GAMMA_RANGE), GAMMA_RANGE); | ||||
img->ss.on = options->slideshow > 0; | |||||
img->ss.delay = options->slideshow > 0 ? options->slideshow : SLIDESHOW_DELAY; | |||||
} | } | ||||
void exif_auto_orientate(const fileinfo_t *file) | void exif_auto_orientate(const fileinfo_t *file) | ||||
@@ -143,9 +146,8 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||||
img->multi.frames = (img_frame_t*) | img->multi.frames = (img_frame_t*) | ||||
s_malloc(sizeof(img_frame_t) * img->multi.cap); | s_malloc(sizeof(img_frame_t) * img->multi.cap); | ||||
} | } | ||||
img->multi.cnt = 0; | img->multi.cnt = img->multi.sel = 0; | ||||
img->multi.sel = 0; | img->multi.length = img->multi.repeat = 0; | ||||
img->multi.repeat = 0; | |||||
#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 | #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 | ||||
gif = DGifOpenFileName(file->path, NULL); | gif = DGifOpenFileName(file->path, NULL); | ||||
@@ -275,6 +277,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||||
} | } | ||||
img->multi.frames[img->multi.cnt].im = im; | img->multi.frames[img->multi.cnt].im = im; | ||||
img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY; | img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY; | ||||
img->multi.length += img->multi.frames[img->multi.cnt].delay; | |||||
img->multi.cnt++; | img->multi.cnt++; | ||||
} | } | ||||
} while (rec != TERMINATE_RECORD_TYPE); | } while (rec != TERMINATE_RECORD_TYPE); | ||||
@@ -35,6 +35,7 @@ typedef struct { | |||||
int cnt; | int cnt; | ||||
int sel; | int sel; | ||||
bool animate; | bool animate; | ||||
int length; | |||||
int repeat; | int repeat; | ||||
} multi_img_t; | } multi_img_t; | ||||
@@ -59,6 +60,11 @@ typedef struct { | |||||
Imlib_Color_Modifier cmod; | Imlib_Color_Modifier cmod; | ||||
int gamma; | int gamma; | ||||
struct { | |||||
bool on; | |||||
int delay; | |||||
} ss; | |||||
multi_img_t multi; | multi_img_t multi; | ||||
} img_t; | } img_t; | ||||
@@ -68,6 +68,7 @@ typedef struct { | |||||
void redraw(void); | void redraw(void); | ||||
void reset_cursor(void); | void reset_cursor(void); | ||||
void animate(void); | void animate(void); | ||||
void slideshow(void); | |||||
void clear_resize(void); | void clear_resize(void); | ||||
appmode_t mode; | appmode_t mode; | ||||
@@ -96,9 +97,10 @@ struct { | |||||
} info; | } info; | ||||
timeout_t timeouts[] = { | timeout_t timeouts[] = { | ||||
{ { 0, 0 }, false, redraw }, | { { 0, 0 }, false, redraw }, | ||||
{ { 0, 0 }, false, reset_cursor }, | { { 0, 0 }, false, reset_cursor }, | ||||
{ { 0, 0 }, false, animate }, | { { 0, 0 }, false, animate }, | ||||
{ { 0, 0 }, false, slideshow }, | |||||
{ { 0, 0 }, false, clear_resize }, | { { 0, 0 }, false, clear_resize }, | ||||
}; | }; | ||||
@@ -304,6 +306,7 @@ void load_image(int new) | |||||
return; | return; | ||||
win_set_cursor(&win, CURSOR_WATCH); | win_set_cursor(&win, CURSOR_WATCH); | ||||
reset_timeout(slideshow); | |||||
if (new != fileidx) | if (new != fileidx) | ||||
alternate = fileidx; | alternate = fileidx; | ||||
@@ -363,6 +366,8 @@ void update_info(void) | |||||
} | } | ||||
} else { | } else { | ||||
n = snprintf(rt, rlen, "%s", mark); | n = snprintf(rt, rlen, "%s", mark); | ||||
if (img.ss.on) | |||||
n += snprintf(rt + n, rlen - n, "%ds | ", img.ss.delay); | |||||
if (img.gamma != 0) | if (img.gamma != 0) | ||||
n += snprintf(rt + n, rlen - n, "G%+d | ", img.gamma); | n += snprintf(rt + n, rlen - n, "G%+d | ", img.gamma); | ||||
n += snprintf(rt + n, rlen - n, "%3d%% | ", (int) (img.zoom * 100.0)); | n += snprintf(rt + n, rlen - n, "%3d%% | ", (int) (img.zoom * 100.0)); | ||||
@@ -389,10 +394,18 @@ void update_info(void) | |||||
void redraw(void) | void redraw(void) | ||||
{ | { | ||||
if (mode == MODE_IMAGE) | int t; | ||||
if (mode == MODE_IMAGE) { | |||||
img_render(&img); | img_render(&img); | ||||
else | if (img.ss.on) { | ||||
t = img.ss.delay * 1000; | |||||
t = img.multi.animate ? MAX(t, img.multi.length) : t; | |||||
set_timeout(slideshow, t, false); | |||||
} | |||||
} else { | |||||
tns_render(&tns); | tns_render(&tns); | ||||
} | |||||
update_info(); | update_info(); | ||||
win_draw(&win); | win_draw(&win); | ||||
reset_timeout(redraw); | reset_timeout(redraw); | ||||
@@ -429,6 +442,12 @@ void animate(void) | |||||
} | } | ||||
} | } | ||||
void slideshow(void) | |||||
{ | |||||
load_image(fileidx + 1 < filecnt ? fileidx + 1 : 0); | |||||
redraw(); | |||||
} | |||||
void clear_resize(void) | void clear_resize(void) | ||||
{ | { | ||||
resized = false; | resized = false; | ||||
@@ -34,7 +34,7 @@ const options_t *options = (const options_t*) &_options; | |||||
void print_usage(void) | void print_usage(void) | ||||
{ | { | ||||
printf("usage: sxiv [-bcdFfhioqrstvZ] [-G GAMMA] [-g GEOMETRY] [-n NUM] " | printf("usage: sxiv [-bcdFfhioqrstvZ] [-G GAMMA] [-g GEOMETRY] [-n NUM] " | ||||
"[-N name] [-z ZOOM] FILES...\n"); | "[-N NAME] [-S DELAY] [-z ZOOM] FILES...\n"); | ||||
} | } | ||||
void print_version(void) | void print_version(void) | ||||
@@ -44,7 +44,7 @@ void print_version(void) | |||||
void parse_options(int argc, char **argv) | void parse_options(int argc, char **argv) | ||||
{ | { | ||||
int opt, t, gamma; | int n, opt; | ||||
char *end; | char *end; | ||||
_options.from_stdin = false; | _options.from_stdin = false; | ||||
@@ -55,6 +55,7 @@ void parse_options(int argc, char **argv) | |||||
_options.scalemode = SCALE_MODE; | _options.scalemode = SCALE_MODE; | ||||
_options.zoom = 1.0; | _options.zoom = 1.0; | ||||
_options.gamma = 0; | _options.gamma = 0; | ||||
_options.slideshow = 0; | |||||
_options.fixed_win = false; | _options.fixed_win = false; | ||||
_options.fullscreen = false; | _options.fullscreen = false; | ||||
@@ -66,7 +67,7 @@ void parse_options(int argc, char **argv) | |||||
_options.thumb_mode = false; | _options.thumb_mode = false; | ||||
_options.clean_cache = false; | _options.clean_cache = false; | ||||
while ((opt = getopt(argc, argv, "bcdFfG:g:hin:N:oqrstvZz:")) != -1) { | while ((opt = getopt(argc, argv, "bcdFfG:g:hin:N:oqrS:stvZz:")) != -1) { | ||||
switch (opt) { | switch (opt) { | ||||
case '?': | case '?': | ||||
print_usage(); | print_usage(); | ||||
@@ -87,13 +88,12 @@ void parse_options(int argc, char **argv) | |||||
_options.fullscreen = true; | _options.fullscreen = true; | ||||
break; | break; | ||||
case 'G': | case 'G': | ||||
gamma = strtol(optarg, &end, 0); | n = strtol(optarg, &end, 0); | ||||
if (*end != '\0') { | if (*end != '\0') { | ||||
fprintf(stderr, "sxiv: invalid argument for option -G: %s\n", | fprintf(stderr, "sxiv: invalid argument for option -G: %s\n", optarg); | ||||
optarg); | |||||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | ||||
} | } | ||||
_options.gamma = gamma; | _options.gamma = n; | ||||
break; | break; | ||||
case 'g': | case 'g': | ||||
_options.geometry = optarg; | _options.geometry = optarg; | ||||
@@ -105,13 +105,12 @@ void parse_options(int argc, char **argv) | |||||
_options.from_stdin = true; | _options.from_stdin = true; | ||||
break; | break; | ||||
case 'n': | case 'n': | ||||
if (sscanf(optarg, "%d", &t) <= 0 || t < 1) { | n = strtol(optarg, &end, 0); | ||||
fprintf(stderr, "sxiv: invalid argument for option -n: %s\n", | if (*end != '\0' || n <= 0) { | ||||
optarg); | fprintf(stderr, "sxiv: invalid argument for option -n: %s\n", optarg); | ||||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | ||||
} else { | |||||
_options.startnum = t - 1; | |||||
} | } | ||||
_options.startnum = n - 1; | |||||
break; | break; | ||||
case 'N': | case 'N': | ||||
_options.res_name = optarg; | _options.res_name = optarg; | ||||
@@ -125,6 +124,14 @@ void parse_options(int argc, char **argv) | |||||
case 'r': | case 'r': | ||||
_options.recursive = true; | _options.recursive = true; | ||||
break; | break; | ||||
case 'S': | |||||
n = strtol(optarg, &end, 0); | |||||
if (*end != '\0' || n <= 0) { | |||||
fprintf(stderr, "sxiv: invalid argument for option -S: %s\n", optarg); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
_options.slideshow = n; | |||||
break; | |||||
case 's': | case 's': | ||||
_options.scalemode = SCALE_FIT; | _options.scalemode = SCALE_FIT; | ||||
break; | break; | ||||
@@ -139,13 +146,13 @@ void parse_options(int argc, char **argv) | |||||
_options.zoom = 1.0; | _options.zoom = 1.0; | ||||
break; | break; | ||||
case 'z': | case 'z': | ||||
_options.scalemode = SCALE_ZOOM; | n = strtol(optarg, &end, 0); | ||||
if (sscanf(optarg, "%d", &t) <= 0 || t <= 0) { | if (*end != '\n' || n <= 0) { | ||||
fprintf(stderr, "sxiv: invalid argument for option -z: %s\n", | fprintf(stderr, "sxiv: invalid argument for option -z: %s\n", optarg); | ||||
optarg); | |||||
exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | ||||
} | } | ||||
_options.zoom = (float) t / 100.0; | _options.scalemode = SCALE_ZOOM; | ||||
_options.zoom = (float) n / 100.0; | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -35,6 +35,7 @@ typedef struct { | |||||
scalemode_t scalemode; | scalemode_t scalemode; | ||||
float zoom; | float zoom; | ||||
int gamma; | int gamma; | ||||
int slideshow; | |||||
/* window: */ | /* window: */ | ||||
bool fixed_win; | bool fixed_win; | ||||
@@ -12,6 +12,8 @@ sxiv \- Simple X Image Viewer | |||||
.IR NAME ] | .IR NAME ] | ||||
.RB [ \-n | .RB [ \-n | ||||
.IR NUM ] | .IR NUM ] | ||||
.RB [ \-S | |||||
.IR DELAY ] | |||||
.RB [ \-z | .RB [ \-z | ||||
.IR ZOOM ] | .IR ZOOM ] | ||||
.IR FILE ... | .IR FILE ... | ||||
@@ -78,6 +80,9 @@ Be quiet, disable warnings to standard error stream. | |||||
.B \-r | .B \-r | ||||
Search the given directories recursively for images to view. | Search the given directories recursively for images to view. | ||||
.TP | .TP | ||||
.BI "\-S " DELAY | |||||
Start in slideshow mode. Set the delay between images to DELAY seconds. | |||||
.TP | |||||
.B \-s | .B \-s | ||||
Scale all images to fit into window. | Scale all images to fit into window. | ||||
.TP | .TP | ||||
@@ -302,6 +307,11 @@ Increase gamma. | |||||
Reset gamma. | Reset gamma. | ||||
.SS Miscellaneous | .SS Miscellaneous | ||||
.TP | .TP | ||||
.B s | |||||
Toggle slideshow mode and/or set the delay between images to | |||||
.I count | |||||
seconds. | |||||
.TP | |||||
.B a | .B a | ||||
Toggle anti-aliasing. | Toggle anti-aliasing. | ||||
.TP | .TP | ||||