#if (!defined(lint) && !defined(SABER))
static char *sid_xvideo_c = "@(#)xvideo.c	1.3 8/7/88 Parallax Graphics Inc";
  static char rcsid_module_c[] = "$Header: VVideo.c,v 1.4 88/08/22 13:07:03 kit Locked $";
  static char rcs_athena_id_c[] = "$Athena: VVideo.c,v 1.4 88/08/22 13:07:03 kit Locked $";
#endif 

/*  This is the video widget, Used for displaying live video into an
 *  X window.
 *
 *	Created: 	8/19/88
 *	By:		Chris D. Peterson
 *                      MIT - Project Athena
 *
 *      $Source: /mit/vtk/Video/RCS/VVideo.c,v $
 *      $Author: kit $
 *      $Header: VVideo.c,v 1.4 88/08/22 13:07:03 kit Locked $
 *	
 */

/*
 * Copyright 1988 by the Massachusetts Institute of Technology
 * 
 * Permission to use, copy, modify, and distribute this
 * software and its documentation for any purpose and without
 * fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright
 * notice and this permission notice appear in supporting
 * documentation, and that the name of M.I.T. not be used in
 * advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 * M.I.T. makes no representations about the suitability of
 * this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 */
 
/*   Copyright (c) 1988 by
 *   PARALLAX GRAPHICS, INCORPORATED, Santa Clara, California.
 *
 *   This software is furnished on an as-is basis, and may be used and copied
 *   only with the inclusion of the above copyright notice.
 *
 *   The information in this software is subject to change without notice.
 *   No committment is made as to the usability or reliability of this
 *   software.
 *
 *   Parallax Graphics, Inc.
 *   2500 Condensa Street
 *   Santa Clara, California  95051
 */

#include <X11/IntrinsicP.h>
#include <stdio.h>
#include <X11/Xos.h>
#include <ctype.h>
#include <X11/StringDefs.h>
#include "VVideoP.h"

/****************************************************************
 *
 * Full class record constant
 *
 ****************************************************************/

/* Private Data */

static XtVideoMode defMode = XtVideoStill;

#define offset(field) XtOffset(VideoWidget, field)
static XtResource resources[] = {
    {XtNvideoMode, XtCVideoMode, XtRVideoMode, sizeof(XtVideoMode),
	offset(video.mode), XtRVideoMode, (caddr_t)&defMode},
    {XtNwidth, XtCWidth, XtRInt, sizeof(Dimension),
	offset(core.width), XtRString, "640"},
    {XtNheight, XtCHeight, XtRInt, sizeof(Dimension),
	offset(core.height), XtRString, "482"},
};

static void Initialize();
static void Redisplay();
static Boolean SetValues();
static void ClassInitialize();

VideoClassRec videoClassRec = {
  {
/* core_class fields */	
#define superclass		(&simpleClassRec)
    /* superclass	  	*/	(WidgetClass) superclass,
    /* class_name	  	*/	"Video",
    /* widget_size	  	*/	sizeof(VideoRec),
    /* class_initialize   	*/	ClassInitialize,
    /* class_part_initialize	*/	NULL,
    /* class_inited       	*/	FALSE,
    /* initialize	  	*/	Initialize,
    /* initialize_hook		*/	NULL,
    /* realize		  	*/	XtInheritRealize,
    /* actions		  	*/	NULL,
    /* num_actions	  	*/	0,
    /* resources	  	*/	resources,
    /* num_resources	  	*/	XtNumber(resources),
    /* xrm_class	  	*/	NULLQUARK,
    /* compress_motion	  	*/	TRUE,
    /* compress_exposure  	*/	TRUE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest	  	*/	FALSE,
    /* destroy		  	*/	NULL,
    /* resize		  	*/	NULL,
    /* expose		  	*/	Redisplay,
    /* set_values	  	*/	SetValues,
    /* set_values_hook		*/	NULL,
    /* set_values_almost	*/	XtInheritSetValuesAlmost,
    /* get_values_hook		*/	NULL,
    /* accept_focus	 	*/	NULL,
    /* version			*/	XtVersion,
    /* callback_private   	*/	NULL,
    /* tm_table		   	*/	NULL,
    /* query_geometry		*/	XtInheritQueryGeometry,
  }
};
WidgetClass videoWidgetClass = (WidgetClass)&videoClassRec;
/****************************************************************
 *
 * Private Procedures
 *
 ****************************************************************/

static void CvtStringToVideoMode();

static XrmQuark	XrmQEstill;
static XrmQuark	XrmQEscaled;
static XrmQuark	XrmQElive;

/*	Function Name: ClassInitialize.
 *	Description: Initialized the video widget class.
 *	Arguments: none.
 *	Returns: none.
 */

static void ClassInitialize()
{

    XrmQEstill   = XrmStringToQuark("still");
    XrmQEscaled = XrmStringToQuark("scaled");
    XrmQElive  = XrmStringToQuark("live");

    XtAddConverter( XtRString, XtRVideoMode, CvtStringToVideoMode, NULL, 0 );
} /* ClassInitialize */

/*	Function Name: CvtStringToVideoMode.
 *	Description: Resource converster for video mode.
 *	Arguments: args, num_args  - from XtAddConverter.
 *                 fromVal - what we need to convert.
 *                 toVal - what we will convert it to.
 *	Returns: none.
 */

/* ARGSUSED */
static void CvtStringToVideoMode(args, num_args, fromVal, toVal)
    XrmValuePtr *args;		/* unused */
    Cardinal	*num_args;	/* unused */
    XrmValuePtr fromVal;
    XrmValuePtr toVal;
{
    static XtVideoMode	e;
    XrmQuark    q;
    char	*s = (char *) fromVal->addr;
    char        lowerName[1000];
    int		i;

    if (s == NULL) return;

    for (i=0; i<=strlen(s); i++) {
        char c = s[i];
	lowerName[i] = isupper(c) ? (char) tolower(c) : c;
    }

    q = XrmStringToQuark(lowerName);

    toVal->size = sizeof(XtVideoMode);
    toVal->addr = (caddr_t) &e;

    if (q == XrmQEstill)   { e = XtVideoStill;   return; }
    if (q == XrmQEscaled)  { e = XtVideoScaled;  return; }
    if (q == XrmQElive)    { e = XtVideoLive;    return; }

    toVal->size = 0;
    toVal->addr = NULL;
};

/*	Function Name: Initialize 
 *	Description: Initialized the video widget.
 *	Arguments: request - what the widget wants to become.
 *                 new - what the widget will become.
 *	Returns: 
 */

/* ARGSUSED */
static void Initialize(request, new)
 Widget request, new;
{
    VideoWidget vw = (VideoWidget) new;
    XGCValues values;

    values.background = vw->core.background_pixel;
    vw->video.gc = XtGetGC( (Widget) vw, 
			   (unsigned) GCForeground | GCBackground, &values);

    vw->video.clear = TRUE;

#ifdef notdef
    vw->video.colormap = XCreateColormap(dpy,
					RootWindow(dpy, DefaultScreen(dpy)),
					DefaultVisual(dpy, DefaultScreen(dpy)),
					AllocNone);
    XSetWindowColormap(dpy, win, vw->video.colormap);
#endif notdef

#ifdef notdef
	XPlxVideoQueryInputSize(dpy, &(vw->video.input));
#else
	vw->video.input.x = 0;
	vw->video.input.y = 0;
	vw->video.input.width = 640;
	vw->video.input.height = 482;
#endif

XSync(XtDisplay(new), FALSE); /* Don't ask me why... */

} /* Initialize */

/*	Function Name: Redisplay.
 *	Description: Repaint the video widget.
 *	Arguments: w - the video widget to repaint.
 *                 junk, garbage - not used.
 *	Returns: none
 */

/* ARGSUSED */
static void Redisplay(w, junk, garbage)
Widget w;
XEvent *junk;
Region garbage;
{
   VideoWidget vw = (VideoWidget) w;
   register Display *dpy = XtDisplay(w);
   register Window win = XtWindow(w);
   
   if (vw->video.clear == TRUE) {
       vw->video.clear = FALSE;
       XClearWindow(dpy, win);
   }

   switch(vw->video.mode) {
   case XtVideoLive:
       XPlxVideoLive(dpy, win, vw->video.gc,
		     vw->video.input.x, vw->video.input.y,
		     0, 0, vw->core.width, vw->core.height);
       break;
   case XtVideoStill:
#ifdef BROKEN_VSTOP       
       XSynchronize( dpy, TRUE );
       XPlxVideoStop(dpy, win, vw->video.gc); 
       XSynchronize( dpy, FALSE );
#else
       XPlxVideoStop(dpy, win, vw->video.gc); 
#endif BROKEN_VSTOP
       XPlxVideoStill(dpy, win, vw->video.gc,
		      vw->video.input.x, vw->video.input.y,
		      0, 0, vw->core.width, vw->core.height);
       break;
   case XtVideoScaled:
#ifdef BROKEN_VSTOP       
       XSynchronize( dpy, TRUE );
       XPlxVideoStop(dpy, win, vw->video.gc); 
       XSynchronize( dpy, FALSE );
#else
       XPlxVideoStop(dpy, win, vw->video.gc); 
#endif BROKEN_VSTOP
       XPlxVideoScale(dpy, win, vw->video.gc,
		      vw->video.input.x, vw->video.input.y,
		      vw->video.input.width, vw->video.input.height,
		      0, 0, vw->core.width, vw->core.height);
       break;
     default:
       XtWarning("Unknown Video mode while displaying video widget.");
       break;
   }
}

/*	Function Name: SetValues.
 *	Description:  Makes sure that a setvalue call is correctly handled.
 *	Arguments: current - what the widget is.
 *                 request - what the widget wants to become.
 *                 new     - what the widget will become.
 *	Returns: none.
 */

/* ARGSUSED */
static Boolean SetValues(current, request, new)
    Widget current, request, new;
{
    VideoWidget curvw = (VideoWidget) current;
    VideoWidget reqvw = (VideoWidget) request;
    VideoWidget newvw = (VideoWidget) new;

    if (reqvw->video.mode != curvw->video.mode) {
        if (curvw->video.mode == XtVideoScaled)
  	    newvw->video.clear = TRUE;
	return(TRUE);
    }
    return(FALSE);
}

/*	Function Name: XtGrabVideoFrame.
 *	Description: Grabs another frame of still or scaled video.
 *	Arguments: w - the video widget.
 *	Returns: none.
 */

void XtGrabVideoFrame(w)
Widget w;
{
    VideoWidget vw = (VideoWidget) w;
    if (vw->video.mode != XtVideoLive)
      Redisplay(w, NULL, NULL);
}

/*	Function Name: XtSetVideoMode.
 *	Description: Allows applications to easily change the video mode.
 *	Arguments: w - the video widget.
 *                 mode - the new mode for this widget.
 *	Returns: none.
 *      NOTE:    This functionality can be had via set values.
 */

void XtSetVideoMode(w, mode)
Widget w;
XtVideoMode mode;
{
    VideoWidget vw = (VideoWidget) w;

    if (mode != vw->video.mode) {
      if (vw->video.mode == XtVideoScaled)
        vw->video.clear = TRUE;
      vw->video.mode = mode;
    }
    Redisplay(w, NULL, NULL);
}
