
/* vserv.c: client interface to video device server */

#include <stdio.h>
#include "videoserver.h"
#include "video_conf.h"

static TUPLE_DESCRIPTOR req_desc;	/* for standard requests */
static TUPLE_DESCRIPTOR rep_desc;	/* for standard replies */
static TUPLE_DESCRIPTOR vtbl_desc; 	/* for device table */

static TUPLE	request;	/* shared request tuple */
static TUPLE	reply;		/* shared reply tuple */

char *getenv();

int	Inited = 0;	/* have tuple descriptors been built yet? */

/* ------------------------------------------------------- */

CONNECTION
OpenLocalVideoServer( vtp )
	VCONF_DEVTABLE *vtp;
{
static char *funcname = "OpenLocalVideoServer";
CONNECTION server;
TUPLE vdev_tuple[MAXDEVS];
RELATION mytable;
TUPLE t;
int	i;
int	stat;
int	reqtype;
int	reqp1, reqp2, reqp3, reqp4;
char	devname[32];
char	reqname[32];
int	devnum;
int	repcode, repval, reperr;
int	foundname = 0;
char	sid[64];
int	port;
char *	dispname;
char	host[64];
int	dispnum;

	if( !vtp )
	{
		fprintf(stderr,"%s: given a NULL video device table.\n",
			funcname);
		return NULL;
	}

	dispname = getenv("DISPLAY");
	if( !dispname )
	{
		fprintf(stderr,
			"%s: unable to get environment variable 'DISPLAY'\n",
			funcname);
		return NULL;
	}

	sscanf(dispname,"%[^:]:%d",host,&dispnum);
	port = VIDSERVE_SERVER_BASE_ID + (10*dispnum);
	sprintf(sid,"%s:#%d",host,port);
			
	fprintf(stderr,"%s: attempting connection to server: %s\n",
		funcname,sid);

	server = start_server_connection(sid, "Dummy parms");

	stat = connection_status(server);
        if (server == NULL || stat != CON_UP) 
	{
		fprintf(stderr,
			"%s: could not start connection to server %s\n",
			funcname,sid);
		return NULL;
	}

	fprintf(stderr,
		"%s: connection to videoserver '%s' started successfully.\n",
		funcname,sid);

	if( !Inited )
	{
	req_desc = create_tuple_descriptor( SERVER_REQUEST_FIELDS, 
		server_request_field_names, server_request_field_types );
	rep_desc = create_tuple_descriptor( STD_REPLY_FIELDS, 
		std_reply_field_names, std_reply_field_types );

	request = create_tuple(req_desc);
	reply = create_tuple(rep_desc);

	vtbl_desc = create_tuple_descriptor( VTBL_FIELDS,
		vtbl_field_names, vtbl_field_types );
	mytable = create_relation( vtbl_desc );
	Inited = 1;
	}

	/* ask the server for the video device table */

	*((int *)FIELD_FROM_TUPLE(request,0)) = VIDSERVE_SERVER_DEVICE;
	*((int *)FIELD_FROM_TUPLE(request,1)) = VIDSERVE_GET_DEVICE_TABLE;

	if (send_object(server, &request, TUPLE_T) == OP_CANCELLED) 
	{
		fprintf(stderr,
		"\n\n%s: GDB send error; can't get video device table.\n",
			funcname);
		return NULL;
	}

	if( receive_object(server, &mytable, RELATION_T) == OP_CANCELLED) 
	{
		fprintf(stderr,
		"\n\n%s: GDB receive error; can't get video device table.\n",
			funcname);
		return NULL;
	}

	/* break the info out of the relation into user's vdt table */

	vtp->ndevs = tuples_in_relation( mytable );

	for( 	i=0, t = FIRST_TUPLE_IN_RELATION(mytable);
				t != NULL;
				i++, t = NEXT_TUPLE_IN_RELATION(mytable,t) )
	{
		vtp->dev[i].type = *(int *)FIELD_FROM_TUPLE(t,0);

		strcpy(vtp->dev[i].name,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,1))));

		strcpy(vtp->dev[i].model,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,2))));

		strcpy(vtp->dev[i].mon_proc,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,3))));

		strcpy(vtp->dev[i].tty,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,4))));
 
		vtp->dev[i].baud = *(int *)FIELD_FROM_TUPLE(t,5);

		vtp->dev[i].parity = *(int *)FIELD_FROM_TUPLE(t,6);

		strcpy(vtp->dev[i].channel,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,7))));
	}

	return server;
}

/* ----------------------------------------------------------- */

int
CloseVideoServer( server )
	CONNECTION server;
{
	sever_connection( server );	
}

/* ------------------------------------------------------- */

CONNECTION
OpenRemoteVideoServer( host, vtp )
	char *host;	/* name of machine where server resides */
	VCONF_DEVTABLE *vtp;
{
static char *funcname = "OpenRemoteVideoServer";
CONNECTION server;
TUPLE vdev_tuple[MAXDEVS];
RELATION mytable;
TUPLE t;
int	i;
int	stat;
int	reqtype;
int	reqp1, reqp2, reqp3, reqp4;
char	devname[32];
char	reqname[32];
int	devnum;
int	repcode, repval, reperr;
int	foundname = 0;
char	sid[64];
int	port;
char *	dispname;
int	dispnum;

	if( !vtp )
	{
		fprintf(stderr,"%s: given a NULL video device table.\n",
			funcname);
		return NULL;
	}

	port = VIDSERVE_SERVER_BASE_ID;	
		/* means server thinks it is outputting to :0 */
	sprintf(sid,"%s:#%d",host,port);
			
	fprintf(stderr,"%s: attempting connection to server: %s\n",
		funcname,sid);

	server = start_server_connection(sid, "Dummy parms");

	stat = connection_status(server);
        if (server == NULL || stat != CON_UP) 
	{
		fprintf(stderr,
			"%s: could not start connection to server %s\n",
			funcname,sid);
		return NULL;
	}

	fprintf(stderr,
		"%s: connection to videoserver '%s' started successfully.\n",
		funcname,sid);

	if( !Inited )
	{
	req_desc = create_tuple_descriptor( SERVER_REQUEST_FIELDS, 
		server_request_field_names, server_request_field_types );
	rep_desc = create_tuple_descriptor( STD_REPLY_FIELDS, 
		std_reply_field_names, std_reply_field_types );

	request = create_tuple(req_desc);
	reply = create_tuple(rep_desc);

	vtbl_desc = create_tuple_descriptor( VTBL_FIELDS,
		vtbl_field_names, vtbl_field_types );
	mytable = create_relation( vtbl_desc );
	Inited = 1;
	}

	/* ask the server for the video device table */

	*((int *)FIELD_FROM_TUPLE(request,0)) = VIDSERVE_SERVER_DEVICE;
	*((int *)FIELD_FROM_TUPLE(request,1)) = VIDSERVE_GET_DEVICE_TABLE;

	if (send_object(server, &request, TUPLE_T) == OP_CANCELLED) 
	{
		fprintf(stderr,
		"\n\n%s: GDB send error; can't get video device table.\n",
			funcname);
		return NULL;
	}

	if( receive_object(server, &mytable, RELATION_T) == OP_CANCELLED) 
	{
		fprintf(stderr,
		"\n\n%s: GDB receive error; can't get video device table.\n",
			funcname);
		return NULL;
	}

	/* break the info out of the relation into user's vdt table */

	vtp->ndevs = tuples_in_relation( mytable );

	for( 	i=0, t = FIRST_TUPLE_IN_RELATION(mytable);
				t != NULL;
				i++, t = NEXT_TUPLE_IN_RELATION(mytable,t) )
	{
		vtp->dev[i].type = *(int *)FIELD_FROM_TUPLE(t,0);

		strcpy(vtp->dev[i].name,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,1))));

		strcpy(vtp->dev[i].model,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,2))));

		strcpy(vtp->dev[i].mon_proc,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,3))));

		strcpy(vtp->dev[i].tty,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,4))));
 
		vtp->dev[i].baud = *(int *)FIELD_FROM_TUPLE(t,5);

		vtp->dev[i].parity = *(int *)FIELD_FROM_TUPLE(t,6);

		strcpy(vtp->dev[i].channel,
			STRING_DATA(*((STRING *)FIELD_FROM_TUPLE(t,7))));
	}

	return server;
}

/* ------------------------------------------------------------- */

int
PerformVideoService( server, string, vtp, code, val, err )
	CONNECTION	server;
	char *		string;
	VCONF_DEVTABLE *vtp;
	int *		code;
	int *		val;
	int *		err;
{
static char *funcname = "PerformVideoService";
int	reqtype;
int	reqp1, reqp2, reqp3, reqp4;
char	devname[32];
char	reqname[32];
int	devnum;
int	repcode, repval, reperr;
int	foundname = 0;
int	i;

	if( !Inited )
	{
		fprintf(stderr,"%s: must call an Open*VideoServer() first.\n",
			funcname);
		return -1;
	}
	if( !server )
	{
		fprintf(stderr,"%s: given a NULL server connection\n",
			funcname);
		return -1;
	}
	if( !vtp )
	{
		fprintf(stderr,"%s: given a NULL video device table.\n",
			funcname);
		return -1;
	}
	if( !string )
	{
		fprintf(stderr,"%s: given a NULL request string.\n",
			funcname);
		return -1;
	}
	if( !code || !val || !err )
	{
		fprintf(stderr,"%s: given a NULL int pointer.\n",
			funcname);
		return -1;
	}

	reqp1 = reqp2 = reqp3 = reqp4 = 0;
	sscanf(string,"%s %s %d %d %d %d\n",
		devname,reqname,&reqp1,&reqp2,&reqp3,&reqp4);
	
	vconf_mkupper( devname );
	vconf_mkupper( reqname );

	for( i=0, foundname = 0; i<vtp->ndevs; i++ )
		if( (vtp->dev[i].type == SWTR_DEV || vtp->dev[i].type == RPD_DEV)
			&& !strcmp(vtp->dev[i].name,devname) )
		{
			foundname = 1;
			devnum = i;
			break;
		}

	if( !foundname && !strcmp(devname,"SERVER") )
		devnum = -1;
	else if( !foundname )
	{
		fprintf(stderr,"%s: unrecognized device: '%s'\n",
			funcname,devname);
		fprintf(stderr,"valid devices are:\n");
		for( i=0; i < vtp->ndevs; i++ )
			if( vtp->dev[i].type == SWTR_DEV || 
				vtp->dev[i].type == RPD_DEV )
			fprintf(stderr,"\t%s (%s)\n",vtp->dev[i].name,
				vconf_nameoftype(vtp->dev[i].type) );
		return -1;
	}

	if( devnum >=0 )
	{
	switch( vtp->dev[devnum].type )
	{
	case RPD_DEV:
		if( !strcmp(reqname,"INDEXON") )
		{
			reqtype = VIDSERVE_CMD;
			reqp1 = INDEX_ON;
		}

		else if( !strcmp(reqname,"INDEXOFF") )
		{
			reqtype = VIDSERVE_CMD;
			reqp1 = INDEX_OFF;
		}

		else if( !strcmp(reqname,"A1ON") )
		{
			reqtype = VIDSERVE_CMD;
			reqp1 = A1_ON;
		}

		else if( !strcmp(reqname,"A1OFF") )
		{
			reqtype = VIDSERVE_CMD;
			reqp1 = A1_OFF;
		}

		else if( !strcmp(reqname,"A2ON") )
		{
			reqtype = VIDSERVE_CMD;
			reqp1 = A2_ON;
		}

		else if( !strcmp(reqname,"A2OFF") )
		{
			reqtype = VIDSERVE_CMD;
			reqp1 = A2_OFF;
		}
	
		else if( !strcmp(reqname,"LOAD") )
		{
			reqtype = VIDSERVE_CMD;
			reqp1 = LOAD;
		}

		else if( !strcmp(reqname,"UNLOAD") )
		{
			reqtype = VIDSERVE_CMD;
			reqp1 = UNLOAD;
		}

		else if( !strcmp(reqname,"@") )
			reqtype = VIDSERVE_GETFRAME;

		else if( !strcmp(reqname,"FJOG") )
		{
			reqtype = VIDSERVE_JOG;
			reqp1 = 1;
		}

		else if( !strcmp(reqname,"RJOG") )
		{
			reqtype = VIDSERVE_JOG;
			reqp1 = -1;
		}

		else if( !strcmp(reqname,"RESET") )
			reqtype = VIDSERVE_RESET;

		else if( !strcmp(reqname,"FMAX") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = F_MAX;
		}

		else if( !strcmp(reqname,"RMAX") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = R_MAX;
		}

		else if( !strcmp(reqname,"FVFAST") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = F_VERY_FAST;
		}

		else if( !strcmp(reqname,"RVFAST") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = R_VERY_FAST;
		}

		else if( !strcmp(reqname,"FFAST") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = F_FAST;
		}

		else if( !strcmp(reqname,"RFAST") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = R_FAST;
		}
		
		else if( !strcmp(reqname,"FPLAY") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = F_PLAY;
		}

		else if( !strcmp(reqname,"RPLAY") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = R_PLAY;
		}

		else if( !strcmp(reqname,"FSLOW") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = F_SLOW;
		}

		else if( !strcmp(reqname,"RSLOW") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = R_SLOW;
		}

		else if( !strcmp(reqname,"FMIN") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = F_VERY_SLOW;
		}

		else if( !strcmp(reqname,"RMIN") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = R_VERY_SLOW;
		}

		else if( !strcmp(reqname,"STILL") )
		{
			reqtype = VIDSERVE_VARSPEED;
			reqp1 = STOP;
		}

		else if( !strcmp(reqname,"SEGPLAY") )
		{
			reqtype = VIDSERVE_SEGPLAY;
		}

		else if( !strcmp(reqname,"SEARCH") )
		{
			reqtype = VIDSERVE_SEARCH;
		}
	
		else
		{	/* error */
			fprintf(stderr,"%s: invalid RPD request\n",
				funcname);
			return -1;
		}

		break;

	case SWTR_DEV:

		if( !strcmp(reqname,"RESET") )
		{
			reqtype = VIDSERVE_RESET;
			reqp1 = 0;
		}

		else if( !strcmp(reqname,"INQUIRE") )
		{
			reqtype = VIDSERVE_INQUIRE;
			reqp1 = 1;	/* assume only one output ... */
		}

		else if( !strcmp(reqname,"VIDEO") )
		{
			reqtype = VIDSERVE_SET_CHAN_SRC;
			reqp2 = reqp1;	/* slight rearrangement */
			reqp1 = VIDEO_CHAN;
			reqp3 = 1;	/* assume only one output ... */
		}

		else if( !strcmp(reqname,"LEFT") )
		{
			reqtype = VIDSERVE_SET_CHAN_SRC;
			reqp2 = reqp1;	/* slight rearrangement */
			reqp1 = LEFT_CHAN;
			reqp3 = 1;	/* assume only one output ... */
		}

		else if( !strcmp(reqname,"RIGHT") )
		{
			reqtype = VIDSERVE_SET_CHAN_SRC;
			reqp2 = reqp1;	/* slight rearrangement */
			reqp1 = RIGHT_CHAN;
			reqp3 = 1;	/* assume only one output ... */
		}

		else if( !strcmp(reqname,"ALL") )
		{
			reqtype = VIDSERVE_SET_CHAN_SRC;
			reqp2 = reqp1;	/* slight rearrangement */
			reqp1 = ALL_CHAN;
			reqp3 = 1;	/* assume only one output ... */
		}

		else
		{	/* error */

			fprintf(stderr,"%s: invalid SWTR request\n",
				funcname);
			return -1;
		}

		break;
	default:
		fprintf(stderr,
			"%s: internal error: bad device type in table!!\n",
			funcname);
		return -1;
		break;
	}	/* end switch */
	}	/* end if */
	
	else	/* server request */
	{
		if( !strcmp(reqname,"LOCK") )
			reqtype = VIDSERVE_LOCK;

		else if( !strcmp(reqname,"UNLOCK") )
			reqtype = VIDSERVE_UNLOCK;

		else if( !strcmp(reqname,"RESET") )
			reqtype = VIDSERVE_RESET;

		else
		{	/* error */
			fprintf(stderr,"%s: invalid SERVER request\n",
				funcname);
			return -1;
		}
		
	}

	*((int *)FIELD_FROM_TUPLE(request,0)) = devnum;
	*((int *)FIELD_FROM_TUPLE(request,1)) = reqtype;
	*((int *)FIELD_FROM_TUPLE(request,2)) = reqp1;
	*((int *)FIELD_FROM_TUPLE(request,3)) = reqp2;
	*((int *)FIELD_FROM_TUPLE(request,4)) = reqp3;
	*((int *)FIELD_FROM_TUPLE(request,5)) = reqp4;

	if (send_object(server, &request, TUPLE_T) == OP_CANCELLED) 
	{
	    fprintf(stderr,
		"\n\n%s: GDB send error; server connection is dead.\n",
			funcname);
	    return -2;
	}

	if( receive_object(server, &reply, TUPLE_T) == OP_CANCELLED) 
	{
		fprintf(stderr,
	"\n\n%s: GDB receive error; server connection is dead.\n",
		funcname);
		return -2;
	}

	*code = *((int *)FIELD_FROM_TUPLE(reply,0));
	*val = *((int *)FIELD_FROM_TUPLE(reply,1));
	*err = *((int *)FIELD_FROM_TUPLE(reply,2));

	return *code;		
}

