 /*
  * Khoros: $Id: lanimate.c,v 1.4 1992/03/20 22:44:24 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: lanimate.c,v 1.4 1992/03/20 22:44:24 dkhoros Exp $";
#endif

 /*
  * $Log: lanimate.c,v $
 * Revision 1.4  1992/03/20  22:44:24  dkhoros
 * VirtualPatch5
 *
  */

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1991, University of New Mexico.  All rights reserved.
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as to the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including, for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"        /* Copyright 1991 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>         File Name: lanimate.c
 >>>>
 >>>>      Program Name: animate
 >>>>
 >>>> Date Last Updated: Thu Dec  5 16:24:43 1991 
 >>>>
 >>>>          Routines: lanimate - the library call for animate
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "xvinclude.h"


/* -library_includes */
#include "animate.h"
/* -library_includes_end */


/****************************************************************
*
* Routine Name: lanimate - library call for animate
*
* Purpose:
*
* Input:
* Output:
* Written By:
*
****************************************************************/


/* -library_def */
int lanimate(img_infile, basename, read_from_memory, shape_infile, 
             clip_infile, cmap_infile, xpos, ypos, update, display_name, 
             use_pixmap, use_iconic, use_cmap, use_root)

char    *img_infile, *basename, *shape_infile, *clip_infile, *cmap_infile;
int     xpos, ypos;
float   update;
char    *display_name;
int     use_pixmap, use_iconic, use_cmap, use_root;
/* -library_def_end */

/* -library_code */
{
        int       index;
        Widget    widget;
        int       direction, update_file();
        char      temp[100];

        xvf_form  *form;
        animate_form   animate_form_info;
        char *form_filestring;
        char *form_pathname;
        struct xvimage *image, *shape, *clip, *cmap,
                       *readimage(), *create_multimage_from_basename();


        /*
         * initialize the display & the forms - 
         * NOTE: assuming a global 'Display *display'
         */
        if (display_name != NULL)
        {
           (void) sprintf(temp, "DISPLAY=%s", display_name);
           vputenv(xvf_strcpy(temp));
        }

        display = xvf_initialize(ac, av, program);
        if (display == NULL)
        {
             fprintf(stderr, "Could not open connection to server");
             exit(0);
        }

        /*
         *  perform global initializations for this application
         */
        xvd_initialize(display);

        if (img_infile != NULL)
        {
            image = readimage(img_infile);
            if (image == NULL) return(false);
        }
        else if (basename != NULL)
        {
            if (read_from_memory)
            {
               image = create_multimage_from_basename(basename);
               if (image == NULL) return(false);
            }
        }
	else
	    image = NULL;

        if (shape_infile != NULL) shape = readimage(shape_infile);
        else shape = NULL;

        if (clip_infile != NULL) clip = readimage(clip_infile);
        else clip = NULL;

        if (cmap_infile != NULL) cmap = readimage(cmap_infile);
        else cmap = NULL;

        /*
         *  After reading in the display image, if use_cmap is False then
         *  we should delete the maps associated with that image.
         */
        if (use_cmap == False && image != NULL)
        {
           if (image->maps != NULL) free(image->maps);
           image->maps              = NULL;
           image->map_storage_type  = VFF_MAPTYP_NONE;
           image->map_scheme        = VFF_MS_NONE;
           image->map_enable        = VFF_MAP_OPTIONAL;
           image->color_space_model = VFF_CM_NONE;
           image->map_row_size    =
           image->map_col_size    =
           image->map_subrow_size = 0;
        }
        else if (cmap != NULL && image != NULL)
        {
           if (image->maps != NULL && image->map_row_size > 0)
              free(image->maps);

           image->map_scheme        = cmap->map_scheme;
           image->map_storage_type  = cmap->map_storage_type;
           image->map_row_size      = cmap->map_row_size;
           image->map_col_size      = cmap->map_col_size;
           image->map_subrow_size   = cmap->map_subrow_size;
           image->map_enable        = cmap->map_enable;
           image->maps_per_cycle    = cmap->maps_per_cycle;
           image->color_space_model = cmap->color_space_model;
           image->maps              = cmap->maps;
           cmap->maps = NULL; 
           freeimage(cmap);
        }

        /*
         *  initialize global xvdisplay structure
         */
        if (!(xvdisplay = xvd_init_xvdisplay(display, image, shape, clip,
                        NULL, True, True, False, NULL)))
        {
           return(FALSE);
        }

        xvf_set_visual(xvdisplay->visual);
        xvf_set_colormap(xvdisplay->colormap);

        /*
         *  Add detect code to update when the image updates.
         */
        if (update != 0.0)
           (void) xvf_detect_file(img_infile, update, update_file, xvdisplay);


        /*
         * Substitute below the correct filename and directory path
         * of the User Interface Description file to be used
         */
        form_filestring = xvf_strcpy("animate.form");
        form_pathname   = xvf_strcpy("KHOROS_HOME/repos/animate");
        form_filestring = vfullpath(form_filestring, form_pathname, NULL);

        /*
         * Create the forms 
         */
        XVF_EXPRESSION = true;
        if (!(form = xvf_create_form(form_filestring, av, ac, SIMPLE, NULL,
                                     xpos, ypos)))
           exit(0);

        /*
         * Initialize the auto-generated information structure
         */
        _xvf_init_animate_form(form,  &animate_form_info);

        /*
         *  build global xvdisplay structure
         */
        if (xvd_build_xvdisplay(xvdisplay) == False)
        {
           return(FALSE);
        }

        widget = animate_form_info.workspace;
        index  = animate_form_info.workspace_index;
        create_display(form, index, widget, use_pixmap, use_iconic, use_root);

        update_animate_forms(form, &animate_form_info, 
                             img_infile, basename, shape_infile, clip_infile);

        /*
         * Map the forms
         */
        xvf_change_active(form, true);
        direction = -1;
        do
        {
             /*
              * run the forms
              */
             form = xvf_run_form();
             if (form == NULL) break;

             if (xvanimate->iconified != form->glyph_state)
             {
                xvanimate->iconified = form->glyph_state;
                refresh_animate();
             }

             /*
              * get information from the master
              */
             _xvf_get_animate_form(form, &animate_form_info);

             /*
              * user clicked on master  action button 'previous'
              */
             if (animate_form_info.quit)
             {
                break;
             }
             else if (animate_form_info.previous)
             {
                if (direction != REVERSE)
                   xvanimate->direction = REVERSE;

                xvanimate->continous = False;
                direction = REVERSE;

                if (xvanimate->direction == FORWARD)
                   advance_frame();
                else
                   reverse_frame();

                update_animate_mode();
             }

             /*
              * user clicked on master  action button 'reverse'
              */
             else if (animate_form_info.reverse)
             {
                xvanimate->continous = True;
                xvanimate->direction = REVERSE;
                update_animate_mode();
                direction = REVERSE;
             }

             /*
              * user clicked on master  action button 'stop'
              */
             else if (animate_form_info.stop)
             {
                xvanimate->continous = False;
                xvanimate->direction = STOP;
                update_animate_mode();
                direction = STOP;
             }

             /*
              * user clicked on master  action button 'forward'
              */
             else if (animate_form_info.forward)
             {
                xvanimate->continous = True;
                xvanimate->direction = FORWARD;
                update_animate_mode();
                direction = FORWARD;
             }

             /*
              * user clicked on master  action button 'next'
              */
             else if (animate_form_info.next)
             {
                if (direction != FORWARD)
                   xvanimate->direction = FORWARD;

                xvanimate->continous = False;
                direction = FORWARD;

                if (xvanimate->direction == FORWARD)
                   advance_frame();
                else
                   reverse_frame();

                update_animate_mode();
             }

             /*
              * action came from the 'animate_options' subform
              */
             else if (animate_form_info.options_subform_selected)
             {
                  run_animate_options(form, animate_form_info.options_subform);
             }

             /*
              * action came from the 'animate_file' subform
              */
             else if (animate_form_info.file_subform_selected)
             {
                  run_animate_file(form, animate_form_info.file_subform);
             }

             xvf_clear_selections(form->db, form->line_num);

        } while (!animate_form_info.quit);

        /*
         *  Clean-up before exiting.  Clear the root window if we are currently
         *  running the animation on the root.  Also call destroy_images to
         *  destroy and free all images.
         */
        if (xvanimate->use_root == True)
           refresh_rootwindow();

        destroy_images(xvanimate);
        return(TRUE);

}    /* end lanimate */


/****************************************************************
*
* Routine Name:  update_file
*
*      Purpose: updates the animation sequence when a change
*               is detected in the input file
*
*       Input:  id       - not used.
*               filename - name of input file
*               data     - cast to xvdisplay structure
*
*       Output: updates the animate sequence
*
*   Written By: Mark Young
*
****************************************************************/

int update_file(id, filename, data)

int  id;
char *filename;
char *data;
{
        struct xvimage *image, *readimage();
        DisplayStructure *xvdisplay = (DisplayStructure *) data;


        if (!(image = readimage(filename)))
           return(False);

        if (xvanimate->use_root == True)
           refresh_rootwindow();

        destroy_images(xvanimate);
	xvdisplay->image = image;
	xvd_update_image(xvdisplay, NULL);
	init_image(xvdisplay);
        return(True);
}

/****************************************************************
*
* Routine Name: create_multimage_from_basename
*
*      Purpose: takes the basename, goes out and gets those
*               files indicated by the basename, and calls
*               vbandcomb() to combine them into a single
*               multiband image for an animation sequence.
*
*       Input:  basename - basename specifying desired image files
*
*       Output: the multiband image composed of all single band
*               images that could be matched to the basename
*
*   Written By: Danielle Argiro
*
****************************************************************/


struct xvimage *create_multimage_from_basename(basename)
char *basename;
{
        struct xvimage *multimage, *readimage();
        char **imagelist, **vlistdir(); 
        char *tmpimgname, temp[MaxLength];
        int  num_images;
        char buffer[MaxLength];
        static char *template= "animate";

        
        imagelist = vlistdir(basename, NULL, XV_FILE, false, &num_images);
        if (imagelist == NULL)
        {
            sprintf(temp, "unable to get images from supplied basename %s",
                          basename);

            xvf_error_wait(temp, "animate", NULL);
            return(NULL);
        }
     
        
        fprintf(stderr, "animate:\n");
        fprintf(stderr, "combining images specified by basename into \n");
        fprintf(stderr, "a single multiband image for animation....");
        tmpimgname = vtempnam(template);
        sprintf(buffer, "vbandcomb -base %s -o %s -m 2", basename, tmpimgname);
        system(buffer);
        multimage = readimage(tmpimgname);

        sprintf(buffer, "\\rm %s", tmpimgname);
        system(buffer);
        vfreelist(imagelist, num_images);
        fprintf(stderr, "done\n");
        
        return(multimage);

}

/****************************************************************
*
* Routine Name: update_animate_forms
*
*      Purpose: Updates the File Input/Output pane of the 
*               animate forms based on command line input
*
*       Input:  form         - pointer to the form tree
*               form_info    - pointer to animate form info structure
*               img_infile   - input image specified on command line
*               basename     - basename specified on command line
*               shape_infile - shape mask specified on command line
*               clip_infile  - clip mask specified on command line
*
*       Output: the multiband image composed of all single band
*               images that could be matched to the basename
*
*   Written By: Danielle Argiro
*
****************************************************************/
update_animate_forms(form, form_info, img_infile, basename, 
                     shape_infile, clip_infile)
xvf_form     *form;
animate_form *form_info;
char *img_infile; 
char *basename;
char *shape_infile;
char *clip_infile;
{
        int index;
        
        if (img_infile != NULL)
        {
            index = form_info->file_subform->file->i_index;
            xvf_change_input(form, index, xvf_inputfile_chng, img_infile, 0); 
        }

        if (basename != NULL)
        {
            index = form_info->file_subform->file->base_index;
            xvf_change_input(form, index, xvf_stringval_chng, basename, 0); 
        }
        
        if (shape_infile != NULL)
        {
            index = form_info->file_subform->file->s_index;
            xvf_change_input(form, index, xvf_inputfile_chng, shape_infile, 0); 
        }

        if (clip_infile != NULL)
        {
            index = form_info->file_subform->file->c_index;
            xvf_change_input(form, index, xvf_inputfile_chng, clip_infile, 0); 
        }
}
/* -library_code_end */
