/* 
    slideshow+ v1.2 Marshall Lake <mlake@melake.erols.com>
*/

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/shape.h>
#include <Imlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void getoutofdodge (char *), help (char *), version (char *);

int main (int argc, char **argv) {
    Display *disp;
    ImlibData *id;
    XSetWindowAttributes attr;
    Window win;
    XEvent ev;
    ImlibImage *im;
    ImlibColorModifier mod;
    extern char *optarg;
    extern int optind;
    FILE *fin;
    int w, h, c, delay = 3, nosnd = 0, status;
    char bname[256], sndfile [256], *per, cmd[256], begcmd[11] = "exec play ";

    /* process options */
    while ((c = getopt (argc, argv, "hvlsd:")) != -1)
        switch (c) {
	       case 'd':
               delay = atoi (optarg);
               if (delay >= 65535)
                   getoutofdodge (argv[0]);
		       break;
           case 'h':
               help (argv[0]);
               break;
           case 'v':
               version (argv[0]);
               break;
           case 's':
               nosnd = 1;
               break;
           case '?':
               getoutofdodge (argv[0]);
	    }
    if (open (argv[optind], O_RDONLY, 0666) == -1)
        getoutofdodge (argv[0]);

    /* if we can't find play then we can't play the sound bites */
    if (!nosnd) {
        status = system ("which play");
        if (WEXITSTATUS (status) == 1) {
            fprintf (stdout, "\nCannot find the \"play\" command.  ");
            fprintf (stdout, "No sound will be played.\n");
            fprintf (stdout, "The \"play\" command should be part of ");
            fprintf (stdout, "the \"sox\" download.\n\n");
            nosnd = 1;
        }
    }

    /* set up for image display */
    disp = XOpenDisplay (NULL);
    id = Imlib_init (disp);
    while (!(im = Imlib_load_image (id, argv[optind])))
        optind++;
    w = im->rgb_width;
    h = im->rgb_height;
    win = XCreateWindow (disp, DefaultRootWindow (disp), 0, 0, w, h, 5,
            id->x.depth, InputOutput, id->x.visual, 0, &attr);
    XStoreName (disp, win, argv[optind]);
    XSelectInput (disp, win, KeyPressMask | ButtonPressMask | StructureNotifyMask);
    XResizeWindow (disp, win, im->rgb_width, im->rgb_height);
    XMapWindow (disp, win);
    XSync (disp, False);

    /* cycle through images */
    while (optind < argc) {
        /* if filename ends in .snd then skip it for display purposes */
        per = rindex (argv[optind], '.');
        if (per)
            if (!strcmp (per, ".snd")) {
                optind++;
                continue;
            }

        /* if file isn't a valid graphic file then go on to the next file */
        if (!(im = Imlib_load_image (id, argv[optind]))) {
            optind++;
            continue;
        }
        XStoreName (disp, win, argv[optind]);

        /* get basename of picture filename */
        per = index (argv[optind], '.');
        if (!per) {
            strcpy (&bname[0], argv[optind]);
            strcat (&bname[0], ".");
        }
        else {
            strncpy (&bname[0], argv[optind], (per - &argv[optind][0]));
            bname[per - &argv[optind][0]] = '.';
            bname[per - &argv[optind][0] + 1] = '\0';
        }

        XResizeWindow (disp, win, im->rgb_width, im->rgb_height);
        XSync (disp, False);					
        Imlib_get_image_modifier (id, im, &mod);
        mod.brightness = 255;
        Imlib_set_image_modifier (id, im, &mod);
        Imlib_apply_image (id, im, win);
        XSync (disp, False);

        /* play the sound bite */
        if (!nosnd) {
            strcpy (&cmd[0], &begcmd[0]);
            strcat (&cmd[0], &bname[0]);
            strcat (&cmd[0], "snd");
            strcpy (&sndfile[0], &bname[0]);
            strcat (&sndfile[0], "snd");
            if (open (sndfile, O_RDONLY, 0666) != -1) {
                fin = popen (cmd, "r");
                pclose (fin);
            }
        }
        /* wait the specified amount of time */
        sleep (delay);

        /* check for the left mouse button to pause the display */
        if (XCheckMaskEvent (disp, ButtonPress, &ev))
            while (1)
                /* un-pause the display when the left mouse button is pressed again */
                if (XCheckMaskEvent (disp, ButtonPress, &ev))
                    break;

        Imlib_kill_image (id, im);

        /* go to the next picture file */
        optind++;
    }

    /* finished */
    XUnmapWindow (disp, win);
    XDestroyWindow (disp, win);
    return 0;
}

/* help */
void
help (char *prgnm) {
    fprintf (stdout,
            "\nUsage:   %s [OPTIONS] <image...>\n\n", prgnm);
    fprintf (stdout, "-h        show this help\n");
    fprintf (stdout, "-v        show version\n");
    fprintf (stdout, "-s        do NOT play any associated sound files\n");
    fprintf (stdout, "-d delay  pause delay seconds (default 3) between\n");
    fprintf (stdout, "          pictures (in addition to the amount of\n");
    fprintf (stdout, "          time it takes to play the associated sound,\n");
    fprintf (stdout, "          if any)\n\n");
    fprintf (stdout, "Press mouse Button 1 to pause the display.\n");
    fprintf (stdout, "Press mouse Button 1 a second time to continue the display.");
    fprintf (stdout, "\n\nExample: %s -d 10 *.jpg\n", prgnm);
    fprintf (stdout, "The above example will display all the readable\n");
    fprintf (stdout, "picture files in the current directory with a file\n");
    fprintf (stdout, "name ending in \".jpg\".  Play any associated sound\n");
    fprintf (stdout, "files.  Delay 10 seconds (plus the time it takes\n");
    fprintf (stdout, "to play the associated sound file) between pictures.");
    fprintf (stdout, "\n\n");
    exit (0);
}

/* failure */
void
getoutofdodge (char *prgnm) {
    fprintf (stdout,
            "\nUsage:   %s [OPTIONS] <image...>\n\n", prgnm);
    fprintf (stdout, "For additional help:\n");
    fprintf (stdout, "%s -h\n", prgnm);
    exit (1);
}

/* print version */
void
version (char *prgnm) {
    fprintf (stdout, "\n%s Version 1.2\n\n", prgnm);
    exit (0);
}

