diff --git a/man/feh.pre b/man/feh.pre index cdfaa155..3d67c617 100644 --- a/man/feh.pre +++ b/man/feh.pre @@ -793,17 +793,26 @@ See for how to reverse it permanently. Default: 20 . -.It Cm -D , --slideshow-delay Ar float -. -For slideshow mode, wait -.Ar float -seconds between automatically changing slides. -Useful for presentations. -Specify a negative number to set the delay -.Pq which will then be Ar float No * (-1) , -but start +.It Cm -D , --slideshow-delay Ar float-list +. +For slideshow mode, you can specify the delay between slide changes in seconds. +If multiple comma seperated delays are specified then these are used with equal +random probability. The list may contain duplicates. +If the list starts with a - (no decimal point) the display starts in paused mode. +A delay of 0 means perpetual delay (no timed slide changes) while a delay of +0.0 gives the least delay possible between slides. +. +As a shorthand you may also specify delays like this: + --slideshow-delay 1.0x10,5x2,10 +.Pp +This will give 10 times the probabiity of 1 second, twice the probability of 5 seconds as well as a single chance of a delay of 10 seconds. +The actual probabilities in this case being 10/13, 2/13 and 1/13 respectively. Real values as well as integers may be used for the multiplier. +.Pp +The Following would give the same as the above but starting .Nm in paused mode. +. + --slideshow-delay -1.0x10,5x2,10 . .It Cm -S , --sort Ar sort_type . diff --git a/src/help.raw b/src/help.raw index 0e99c689..3b409f62 100644 --- a/src/help.raw +++ b/src/help.raw @@ -41,6 +41,8 @@ OPTIONS --auto-rotate Rotate images according to Exif info (if compiled with exif=1) -^, --title TITLE Set window title (see FORMAT SPECIFIERS) -D, --slideshow-delay NUM Set delay between automatically changing slides + NUM,NUM,NUM or NUMxMult,NUMxMult also allowed, + gives random delays equally or according to multipliers. --on-last-slide quit Exit after one loop through the slide show (old --cycle-once) --on-last-slide hold Stop at both ends of the filelist -R, --reload NUM Reload images after NUM seconds diff --git a/src/keyevents.c b/src/keyevents.c index 2f9b1d67..f3770d24 100644 --- a/src/keyevents.c +++ b/src/keyevents.c @@ -699,7 +699,7 @@ void feh_event_handle_generic(winwidget winwid, unsigned int state, KeySym keysy * editing captions in slideshow mode does not make any sense * at all; this is just in case someone accidentally does it... */ - if (opt.slideshow_delay) + if (opt.slideshow_delay==NULL) opt.paused = 1; winwid->caption_entry = 1; } diff --git a/src/options.c b/src/options.c index 3f405faa..0a6c8e92 100644 --- a/src/options.c +++ b/src/options.c @@ -53,7 +53,7 @@ void init_parse_options(int argc, char **argv) memset(&opt, 0, sizeof(fehoptions)); opt.display = 1; opt.aspect = 1; - opt.slideshow_delay = 0.0; + opt.slideshow_delay = NULL; opt.conversion_timeout = -1; opt.thumb_w = 60; opt.thumb_h = 60; @@ -479,14 +479,25 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) imlib_add_path_to_font_path(optarg); break; case OPTION_slideshow_delay: - opt.slideshow_delay = atof(optarg); - if (opt.slideshow_delay < 0.0) { - opt.slideshow_delay *= (-1); - opt.paused = 1; - } else { - opt.paused = 0; - } - break; + if (strcmp(optarg,"0")==0) + { + opt.slideshow_delay=realloc(opt.slideshow_delay,0); + opt.slideshow_delay=NULL; + opt.paused = 1; + } + else if (*optarg=='-') + { + opt.slideshow_delay=(char *) realloc(opt.slideshow_delay,strlen(optarg)); + strcpy(opt.slideshow_delay,optarg+1); + opt.paused = 1; + } + else + { + opt.slideshow_delay=(char *) realloc(opt.slideshow_delay,strlen(optarg)+1); + strcpy(opt.slideshow_delay,optarg); + opt.paused = 0; + } + break; case OPTION_thumb_height: opt.thumb_h = atoi(optarg); break; diff --git a/src/options.h b/src/options.h index 2aed6a61..a05923a2 100644 --- a/src/options.h +++ b/src/options.h @@ -145,7 +145,7 @@ struct __fehoptions { unsigned char mode; unsigned char paused; - double slideshow_delay; + char *slideshow_delay; signed int conversion_timeout; diff --git a/src/slideshow.c b/src/slideshow.c index 3944a685..98407e6a 100644 --- a/src/slideshow.c +++ b/src/slideshow.c @@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "options.h" #include "signals.h" +double get_ssd(char *s); void init_slideshow_mode(void) { winwidget w = NULL; @@ -54,6 +55,11 @@ void init_slideshow_mode(void) * wrong file. */ + if (opt.slideshow_delay && strcmp(opt.slideshow_delay,"0")==0) + { + opt.slideshow_delay=(char *) realloc(opt.slideshow_delay,0); + opt.slideshow_delay=NULL; + } // 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)) { @@ -109,8 +115,9 @@ void init_slideshow_mode(void) 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.slideshow_delay && strcmp(opt.slideshow_delay,"0")!=0) + feh_add_timer(cb_slide_timer, w, get_ssd(opt.slideshow_delay), "SLIDE_CHANGE"); + if (opt.reload > 0) feh_add_unique_timer(cb_reload_timer, w, opt.reload); break; @@ -202,8 +209,8 @@ void slideshow_change_image(winwidget winwid, int change, int render) */ int our_filelist_len = filelist_len; - if (opt.slideshow_delay > 0.0) - feh_add_timer(cb_slide_timer, winwid, opt.slideshow_delay, "SLIDE_CHANGE"); + if (opt.slideshow_delay && strcmp(opt.slideshow_delay,"0")!=0) + feh_add_timer(cb_slide_timer, winwid, get_ssd(opt.slideshow_delay), "SLIDE_CHANGE"); /* Without this, clicking a one-image slideshow reloads it. Not very * intelligent behaviour :-) */ @@ -690,3 +697,70 @@ gib_list *feh_list_jump(gib_list * root, gib_list * l, int direction, int num) } return (ret); } +/**************************************************************************/ +/* This function entirely responsible for interpreting the data + * from opt.slideshow_delay - its called each time an image is displayed + * and a random delay selected from the list. (Can be a list of 1 item) + * ************************************************************************/ +double get_ssd(char *s) +{ + static int k=-1; + static float sumprob; + static int xflag=0; + + float prob=0.0; + float thisprob=1.0; + float r; // the random number + char *q; + char *p; + + p=s; // reset pointer to start + if (k<0) // all this done just once as k static sumprob and xflag also static + { + k=0; + srand(time(NULL)); // seed random num gen, just once. + // count the commas, sum probabilities + while (*p) + { + if (*p==',' || *(p+1)==0) // start of new item in list or end of list + { + k++; + prob+=thisprob; + thisprob=1.0; // reset probablity of this item + } + if (*p=='x') + { + xflag=1; + if (atof(p+1)>0) thisprob=atof(p+1); + } + p++; + } + sumprob=prob; + p=s; + } + + if (k==1 && xflag==0) + return atof(s); // deal with simplest case, just one value + + r=sumprob*rand() / (float)RAND_MAX; // assign random number + + // count the commas, sum probabilities, select value + // repeating much the same as above but abort when we get to where we are going. + // remember the above is only done once, but this is done every time. + prob=0.0; + thisprob=1.0; // default if no x given , one time + q=p; // this will be the result + while (*p) + { + if (*p==',' || *(p+1)==0) + { + prob+=thisprob; + if (prob>r) break; + q=p+1; + thisprob=1.0; + } + if (*p=='x' && atof(p+1)>0) thisprob=atof(p+1); + p++; + } + return atof(q); +}