/*
 * Copyright 1988, 1989, 1990, 1991 Massachusetts Institute of Technology
 */


/* pe8x1_driver.c: a driver for the PE 8x1 vertical interval switcher
   modified by Hal Birkeland from the a4x1 driver.

   NOTE: the PE switch only switches the audio channels as one,
   hence the bizarreness in sound switching! */


#include "pe8x1.h"
#include "structs.h"

#define min(x,y) ( (x<y) ? x:y)
#define max(x,y) ( (x>y) ? x:y)

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

static int	/* private, internal utility routine */
pe8x1_set_state( swtr, output, v, a1, a2 )
	
	SWTR_ptr swtr;
	int	output;		/* the number of the output */
	int	v,a1,a2;	/* the number of the input on that channel */

{
  if( !output || output < 1 || output > NUM_OUTPUTS || !swtr)
    return 0;
  output -= 1;	/* adjust for zero-base */

  /* if anything is 0, leave it alone */
  if (v) swtr->state[output].VideoSource = v = min (max (1,v), NUM_INPUTS);
  if (a1) swtr->state[output].LeftSource = a1 = min (max (1,a1), NUM_INPUTS);
  if (a2) swtr->state[output].RightSource = a2 = min (max (1,a2), NUM_INPUTS);
  
  return 0;
}

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

int
pe8x1_reset (swtr)
     SWTR_ptr swtr;
{
  char	cmd[10];
  
  if (!swtr) return -1;
  if (swtr->fd<0) return -1;

  /* XXX */
  sprintf(cmd, "@!1");
  ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
  pe8x1_set_state( swtr, 1, 1, 1, 1 );
  return 0;
}

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

int
pe8x1_set_chan_src( swtr, chan, srcnum, output )
     SWTR_ptr swtr;
     int output;	
     int chan;
     int srcnum;
{
  int	ret = -1;
  char	cmd[10];
  int curvid, curch1, curch2;

  if (!swtr) return -1;
  if (swtr->fd < 0) return -1;
  
  pe8x1_inquire (swtr, output, &curvid, &curch1, &curch2);

  if (chan != ALL_CHAN) {
    if ((chan & VIDEO_CHAN) && (curvid == srcnum))
      chan &= (LEFT_CHAN | RIGHT_CHAN);
    if ((chan & LEFT_CHAN) && (curch1 == srcnum))
      chan &= (VIDEO_CHAN | RIGHT_CHAN);
    if ((chan & RIGHT_CHAN) && (curch2 == srcnum))
      chan &= (VIDEO_CHAN | LEFT_CHAN);
  }

  /* 
   * RMS mod 1/10/91; if we make a change to the state
   * of the video channel, we should wait until we're sure
   * the switch has been made before returning; this could
   * cause video digitizers (for example) to get a bad frame
   * or a frame from the wrong video source.
   */

  srcnum = min ( max(1,srcnum), NUM_INPUTS);
  
  /* XXX */
  switch(chan) {
  case VIDEO_CHAN:
    sprintf(cmd, "@V%d", srcnum );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
    if(curvid != srcnum)
      mpause(200);
    pe8x1_set_state( swtr, output, srcnum, 0, 0 );
    break;
    /*  case LEFT_CHAN:
	sprintf(cmd, "@L%d", srcnum );
	ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
	pe8x1_set_state( swtr, output, 0, srcnum, 0 );
	break; */
    /*  case RIGHT_CHAN:
	sprintf(cmd, "@R%d", srcnum );
	ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
	pe8x1_set_state( swtr, output, 0, 0, srcnum );
	break; */
  case ALL_CHAN:
    sprintf(cmd, "@!%d", srcnum );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
    pe8x1_set_state( swtr, output, srcnum, srcnum, srcnum );
    if(curvid != srcnum)
      mpause(200);
    break;
  case (RIGHT_CHAN | LEFT_CHAN):
    sprintf(cmd, "@L%d", srcnum );
    ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
    pe8x1_set_state( swtr, output, 0, srcnum, srcnum );
    break;
    /*  case (RIGHT_CHAN | VIDEO_CHAN):
	sprintf(cmd, "@R%d", srcnum );
	ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
	sprintf(cmd, "@V%d", srcnum );
	ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
	pe8x1_set_state( swtr, output, srcnum, 0, srcnum);
	break; */
    /* case (LEFT_CHAN | VIDEO_CHAN):
       sprintf(cmd, "@V%d", srcnum );
       ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
       sprintf(cmd, "@L%d", srcnum );
       ttyutil_write( swtr->fd, cmd, strlen(cmd), 10 );
       pe8x1_set_state( swtr, output, srcnum, srcnum, 0 );
       break; */
  default:
    return (-1);
    break;
  }
  return 0;
}

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

int
pe8x1_inquire( swtr, output, vsrc, lsrc, rsrc )
     SWTR_ptr swtr;
     int  output;
     int *vsrc;
     int *lsrc;
     int *rsrc;
{
  if( output < 1 || output > NUM_OUTPUTS || !swtr)
    return -1;	/* don't mess with the channel return values */
  output -= 1;		/* adjust for zero-base */

  *vsrc = swtr->state[output].VideoSource;
  *lsrc = swtr->state[output].LeftSource;
  *rsrc = swtr->state[output].RightSource;
  return 0;
}

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

int
pe8x1_setfuncs( swtr )
     SWTR_ptr	swtr;
{
  swtr->reset = pe8x1_reset;
  swtr->set_chan_src = pe8x1_set_chan_src;
  swtr->inquire = pe8x1_inquire;
  swtr->inputs = NUM_INPUTS;	
  swtr->outputs = NUM_OUTPUTS;	
  return 0;
}

