/*
 * Copyright 1988, 1989, 1990, 1991 Massachusetts Institute of Technology
 */
#include "structs.h"

/* parm 1 is the volume number
   parm 2 is the number of frames */
DoAlloc(msgsock, hostcommand, clinum)
     int msgsock, clinum;
     Galatea_packet *hostcommand;
{
  RPD_SEGLIST *temp_seglist, *cur_seglist;
  int ret;

  if (clients[clinum].rev != revision) {
    if (sendint(msgsock, (int)VOLUME_LIST_OLD) == -1) return(-1);
    else return(-2);
  }
  if (hostcommand->parm[1] >= num_volumes ||
      volumes[hostcommand->parm[1]].output != clients[clinum].output) {
    if (sendint(msgsock, (int)BAD_VOLUME) == -1) return(-1);
    else return(-2);
  }
  if (volumes[hostcommand->parm[1]].type != RPD_DEV ||
      volumes[hostcommand->parm[1]].recordable == 0) {
    if (sendint(msgsock, (int)FUNC_NOT_SUPPORTED) == -1) return(-1);
    else return(-2);
  }
  ret = vid_alloc(players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]], hostcommand->parm[2]);
  if (DEBUG && ret == -1) printf("DoAlloc: COULDNT_ALLOC\n");
  if (ret == -1) ret = COULDNT_ALLOC;
  else {
    temp_seglist = (RPD_SEGLIST *)calloc(1, sizeof(RPD_SEGLIST));
    if (temp_seglist == (RPD_SEGLIST *)NULL) {
      vfree(players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]], ret, hostcommand->parm[2]);
      if (sendint(msgsock, (int)COULDNT_DO_FUNC) == -1) return(-1);
      else return(-2);
    }
    temp_seglist->start = ret;
    temp_seglist->nframes = hostcommand->parm[2];
    temp_seglist->volume_id = hostcommand->parm[1];
    strcpy(temp_seglist->volume_name, volumes[hostcommand->parm[1]].volume);
    temp_seglist->next = (RPD_SEGLIST *)NULL;
    cur_seglist = clients[clinum].seglist;
    if (cur_seglist == (RPD_SEGLIST *)NULL) 
      clients[clinum].seglist = temp_seglist;
    else {
      while (cur_seglist->next != (RPD_SEGLIST *)NULL) {
	if (cur_seglist->start < temp_seglist->start &&
	    cur_seglist->next->start > temp_seglist-> start)
	  break;
	cur_seglist = cur_seglist->next;
      }
      temp_seglist->next = cur_seglist->next;
      cur_seglist->next = temp_seglist;
    }
  }
  if (DEBUG && ret != COULDNT_ALLOC) {
    printf("Segment allocated: start = %d, nframes = %d, volume = %d\n",
	   temp_seglist->start, temp_seglist->nframes,
	   temp_seglist->volume_id);
  }
  if (sendint(msgsock, ret) == -1) return(-1);
  else return(-2);
}

/* parm 1 is the volume number
   parm 2 is the start requested frame
   parm 3 is the number of frames */
DoAllocAtFrame(msgsock, hostcommand, clinum)
     int msgsock, clinum;
     Galatea_packet *hostcommand;
{
  RPD_SEGLIST *temp_seglist, *cur_seglist;
  int ret;

  if (clients[clinum].rev != revision) {
    if (sendint(msgsock, (int)VOLUME_LIST_OLD) == -1) return(-1);
    else return(-2);
  }
  if (hostcommand->parm[1] >= num_volumes ||
      volumes[hostcommand->parm[1]].output != clients[clinum].output) {
    if (sendint(msgsock, (int)BAD_VOLUME) == -1) return(-1);
    else return(-2);
  }
  if (volumes[hostcommand->parm[1]].type != RPD_DEV ||
      volumes[hostcommand->parm[1]].recordable == 0) {
    if (sendint(msgsock, (int)FUNC_NOT_SUPPORTED) == -1) return(-1);
    else return(-2);
  }
  if (DEBUG) printf("DoAllocAtFrame: attemping to allocate %d frames starting at frame %d on volume %d\n",
		    hostcommand->parm[3], hostcommand->parm[2],
		    hostcommand->parm[1]);
  ret = vid_allocatframe(players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]], hostcommand->parm[2], hostcommand->parm[3]);
  if (DEBUG && ret == -1) printf("DoAllocAtFrame: COULDNT_ALLOC\n");
  if (ret == -1) ret = COULDNT_ALLOC;
  else {
    temp_seglist = (RPD_SEGLIST *)calloc(1, sizeof(RPD_SEGLIST));
    if (temp_seglist == (RPD_SEGLIST *)NULL) {
      vfree(players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]], hostcommand->parm[2], hostcommand->parm[3]);
      if (sendint(msgsock, (int)COULDNT_DO_FUNC) == -1) return(-1);
      else return(-2);
    }
    temp_seglist->start = ret;
    temp_seglist->nframes = hostcommand->parm[3];
    temp_seglist->volume_id = hostcommand->parm[1];
    strcpy(temp_seglist->volume_name, volumes[hostcommand->parm[1]].volume);
    temp_seglist->next = (RPD_SEGLIST *)NULL;
    cur_seglist = clients[clinum].seglist;
    if (cur_seglist == (RPD_SEGLIST *)NULL) 
      clients[clinum].seglist = temp_seglist;
    else {
      while (cur_seglist->next != (RPD_SEGLIST *)NULL) {
	if (cur_seglist->start < temp_seglist->start &&
	    cur_seglist->next->start > temp_seglist-> start)
	  break;
	cur_seglist = cur_seglist->next;
      }
      temp_seglist->next = cur_seglist->next;
      cur_seglist->next = temp_seglist;
    }
  }
  if (DEBUG && ret != COULDNT_ALLOC) {
    printf("Segment allocated: start = %d, nframes = %d, volume = %d\n",
	   temp_seglist->start, temp_seglist->nframes, 
	   temp_seglist->volume_id);
  }
  if (sendint(msgsock, ret) == -1) return(-1);
  else return(-2);
}

/* parm 1 is volume
   parm 2 is start frame
   parm 3 is number of frames */
DoFree(msgsock, hostcommand, clinum)
     int msgsock, clinum;
     Galatea_packet *hostcommand;
{
  RPD_SEGLIST *cur_seglist, *temp_seglist;
  int ret;

  if (clients[clinum].rev != revision) {
    if (sendint(msgsock, (int)VOLUME_LIST_OLD) == -1) return(-1);
    else return(-2);
  }
  if (hostcommand->parm[1] >= num_volumes ||
      volumes[hostcommand->parm[1]].output != clients[clinum].output) {
    if (sendint(msgsock, (int)BAD_VOLUME) == -1) return(-1);
    else return(-2);
  }
  if (volumes[hostcommand->parm[1]].type != RPD_DEV ||
      volumes[hostcommand->parm[1]].recordable == 0) {
    if (sendint(msgsock, (int)FUNC_NOT_SUPPORTED) == -1) return(-1);
    else return(-2);
  }
  /* Make sure no part of the freed area is on the usedlist for the player */
  cur_seglist = players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]]->usedlist;
  while (cur_seglist != (RPD_SEGLIST *)NULL) {
    if ((hostcommand->parm[2] >= cur_seglist->start &&
	hostcommand->parm[2] < cur_seglist->start+cur_seglist->nframes) ||
	(hostcommand->parm[2] < cur_seglist->start &&
	 hostcommand->parm[2] + hostcommand->parm[3] >= cur_seglist->start)) {
      /* Is in usedlist */
      if (sendint(msgsock, (int)COULDNT_FREE) == -1) return(-1);
      else return(-2);
    }
    else cur_seglist = cur_seglist->next;
  }
  cur_seglist = clients[clinum].seglist;
  while (cur_seglist != (RPD_SEGLIST *)NULL) {
    if (cur_seglist->volume_id == hostcommand->parm[1] &&
	hostcommand->parm[2] >= cur_seglist->start &&
	hostcommand->parm[2] < cur_seglist->start+cur_seglist->nframes &&
	(hostcommand->parm[2] + hostcommand->parm[3] <=
	 cur_seglist->start + cur_seglist->nframes))
      break;
    cur_seglist = cur_seglist->next;
  }
  if (cur_seglist == (RPD_SEGLIST *)NULL) {
    if (sendint(msgsock, (int)BAD_ARGUMENT) == -1) return(-1);
    else return(-2);
  }
  ret = vfree(players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]], hostcommand->parm[2], hostcommand->parm[3]);
  if (cur_seglist->start == hostcommand->parm[2]) {
    /* At beginning of seg */
    if (DEBUG) {
      printf("DoFree: freeing from beginning of segment\n");
      printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	     cur_seglist->nframes);
    }
    cur_seglist->start+=hostcommand->parm[3];
    cur_seglist->nframes-=hostcommand->parm[3];
    if (DEBUG) 
      printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	     cur_seglist->nframes);
  }
  else if (cur_seglist->start+cur_seglist->nframes ==
	   hostcommand->parm[2] + hostcommand->parm[3]) {
    /* At end of of seg */
    if (DEBUG) {
      printf("DoFree: freeing from end of segment\n");
      printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	     cur_seglist->nframes);
    }
    cur_seglist->nframes-=hostcommand->parm[3];
    if (DEBUG) 
      printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	     cur_seglist->nframes);
  }
  else {
    /* In middle of seg, hardest case */
    if (DEBUG) {
      printf("DoFree: freeing from middle of segment\n");
      printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	     cur_seglist->nframes);
    }
    temp_seglist = (RPD_SEGLIST *)calloc(1, sizeof(RPD_SEGLIST));
    if (temp_seglist == (RPD_SEGLIST *)NULL) {
      if (sendint(msgsock, (int)COULDNT_FREE) == -1) return(-1);
      else return(-2);
    }
    temp_seglist->start = hostcommand->parm[2]+hostcommand->parm[3];
    temp_seglist->nframes = cur_seglist->start+cur_seglist->nframes-
      (hostcommand->parm[2] + hostcommand->parm[3]);
    temp_seglist->volume_id = cur_seglist->volume_id;
    temp_seglist->next = cur_seglist->next;
    cur_seglist->next = temp_seglist;
    cur_seglist->nframes = hostcommand->parm[2] - cur_seglist->start;
    if (DEBUG) {
      printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	     cur_seglist->nframes);
      printf("New segment: start = %d, nframes = %d\n",
	     temp_seglist->start,
	     temp_seglist->nframes);
    }
  }

  if (ret == -1) ret = COULDNT_FREE;
  else ret = NO_ERROR;

  if (sendint(msgsock, ret) == -1) return(-1);
  else return(-2);
}

/* parm 1 is dest volume
   parm 2 is start frame 
   parm 3 is end frame
   parm 4 is speed 
   parm 5 is mask
   parm 6 is source volume
   parm 7 is return_flag
   parm 8 sync */
DoRecord(msgsock, hostcommand, clinum)
     int msgsock, clinum;
     Galatea_packet *hostcommand;
{
  RPD_ptr rpd;
  Output sourceout, outputvolumeoutput();
  RPD_SEGLIST *cur_seglist, *temp_seglist;
  int ret, record_frames;

  if (clients[clinum].rev != revision) {
    if (!hostcommand->parm[8]) return(sendint(msgsock, (int)VOLUME_LIST_OLD));
    else return(-2);
  }
  if (hostcommand->parm[1] >= num_volumes ||
      volumes[hostcommand->parm[1]].output != clients[clinum].output ||
      hostcommand->parm[6] >= num_volumes ||
      volumes[hostcommand->parm[6]].output != clients[clinum].output) {
    if (!hostcommand->parm[8]) return(sendint(msgsock, (int)BAD_VOLUME));
    else return(-2);
  }
  cur_seglist = clients[clinum].seglist;
  while (cur_seglist != (RPD_SEGLIST *)NULL) {
    if (hostcommand->parm[1] == cur_seglist->volume_id &&
	hostcommand->parm[2] >= cur_seglist->start &&
	hostcommand->parm[3] >= cur_seglist->start &&
	hostcommand->parm[2] < cur_seglist->start + cur_seglist->nframes &&
	hostcommand->parm[3] < cur_seglist->start + cur_seglist->nframes)
      break;
    cur_seglist = cur_seglist->next;
  }
  if (cur_seglist == (RPD_SEGLIST *)NULL) {
    if (!hostcommand->parm[8]) return(sendint(msgsock, (int)VIOLATE_ALLOC));
    else return(-2);
  }

  rpd = players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]];
  if (volumes[hostcommand->parm[1]].type != RPD_DEV ||
      volumes[hostcommand->parm[1]].recordable == 0 ||
      !(rpd->record)) {
    if (!hostcommand->parm[8]) 
      return(sendint(msgsock, (int)FUNC_NOT_SUPPORTED));
    else return(-2);
  }
  if (MAX_LOCK_TIME && hostcommand->parm[4] &&
      abs((hostcommand->parm[3] - hostcommand->parm[2]) / hostcommand->parm[4])
      > MAX_LOCK_TIME && hostcommand->parm[7] == RETURN_SYNC) {
    if (!hostcommand->parm[8]) return(sendint(msgsock,(int)SEGMENT_TOO_LONG));
    else return(-2);
  }

  if (hostcommand->parm[5]) {
    sourceout = outputvolumeoutput(hostcommand->parm[6], players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]]->pseudo_out);
    ret = doswitchtree(sourceout, hostcommand->parm[5], players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]]->pseudo_out);
    if (ret == -1) {
      if (!hostcommand->parm[8]) return(sendint(msgsock, (int)COULDNT_ROUTE));
      else return(-2);
    }
  }
  if (DEBUG) printf("DoRecord: recording from %d to %d\n",
		    hostcommand->parm[2], hostcommand->parm[3]);
  ret = (*rpd->record)(rpd, hostcommand->parm[2], hostcommand->parm[3],
		       hostcommand->parm[4], hostcommand->parm[7]);
  if (ret != -1) {
    used_segment(rpd,hostcommand->parm[2],
		 hostcommand->parm[3]-hostcommand->parm[2]);
    record_frames = hostcommand->parm[3] - hostcommand->parm[2] + 1;
    if (cur_seglist->start == hostcommand->parm[2]) {
      /* At beginning of seg */
      if (DEBUG) {
	printf("DoRecord: freeing from beginning of segment\n");
	printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
      }
      cur_seglist->start+=record_frames;
      cur_seglist->nframes-=record_frames;
      if (DEBUG) 
	printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
    }
    else if (cur_seglist->start+cur_seglist->nframes ==
	     hostcommand->parm[2] + record_frames) {
      /* At end of of seg */
      if (DEBUG) {
	printf("DoRecord: freeing from end of segment\n");
	printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
      }
      cur_seglist->nframes-=record_frames;
      if (DEBUG) 
	printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
    }
    else {
      /* In middle of seg, hardest case */
      if (DEBUG) {
	printf("DoRecord: freeing from middle of segment\n");
	printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
      }
      temp_seglist = (RPD_SEGLIST *)calloc(1, sizeof(RPD_SEGLIST));
      if (temp_seglist == (RPD_SEGLIST *)NULL) {
	if (!hostcommand->parm[8]) return(sendint(msgsock, (int)COULDNT_FREE));
	else return(-2);
      }
      temp_seglist->start = hostcommand->parm[2]+record_frames;
      temp_seglist->nframes = cur_seglist->start+cur_seglist->nframes-
	(hostcommand->parm[2] + record_frames);
      temp_seglist->volume_id = cur_seglist->volume_id;
      temp_seglist->next = cur_seglist->next;
      cur_seglist->next = temp_seglist;
      cur_seglist->nframes = hostcommand->parm[2] - cur_seglist->start;
      if (DEBUG) {
	printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
	printf("New segment: start = %d, nframes = %d\n",
	       temp_seglist->start,
	       temp_seglist->nframes);
      }
    }
  }
  if (ret == -1) {
    if (!hostcommand->parm[8]) return(sendint(msgsock, (int)COULDNT_DO_FUNC));
    else return(-2);
  }
  if (!hostcommand->parm[8]) return(sendint(msgsock, (int)NO_ERROR));
  else return(-2);
}

/* parm 1 is dest volume
   parm 2 is deststart frame 
   parm 3 is destend frame
   parm 4 is destspeed 
   parm 5 is source volume
   parm 6 is srcstart frame
   parm 7 is srcspeed
   parm 8 is mask
   parm 9 is return_flag
   sync is sent separately */
DoDub(msgsock, hostcommand, clinum)
     int msgsock, clinum;
     Galatea_packet *hostcommand;
{
  RPD_ptr rpd, srcrpd;
  Output sourceout, outputvolumeoutput();
  RPD_SEGLIST *cur_seglist, *temp_seglist;
  int ret, record_frames, resource, i, syncval, timeout;

  if ((syncval = serv_acceptint(msgsock, MAX_BLOCK)) == -1)
    return -1;

  if (clients[clinum].rev != revision) {
    if (!syncval) return(sendint(msgsock, (int)VOLUME_LIST_OLD));
    else return(-2);
  }
  if (hostcommand->parm[1] >= num_volumes ||
      volumes[hostcommand->parm[1]].output != clients[clinum].output ||
      hostcommand->parm[5] >= num_volumes ||
      volumes[hostcommand->parm[5]].output != clients[clinum].output) {
    if (!syncval) return(sendint(msgsock, (int)BAD_VOLUME));
    else return(-2);
  }
  cur_seglist = clients[clinum].seglist;
  while (cur_seglist != (RPD_SEGLIST *)NULL) {
    if (hostcommand->parm[1] == cur_seglist->volume_id &&
	hostcommand->parm[2] >= cur_seglist->start &&
	hostcommand->parm[3] >= cur_seglist->start &&
	hostcommand->parm[2] < cur_seglist->start + cur_seglist->nframes &&
	hostcommand->parm[3] < cur_seglist->start + cur_seglist->nframes)
      break;
    cur_seglist = cur_seglist->next;
  }
  if (cur_seglist == (RPD_SEGLIST *)NULL) {
    if (!syncval) return(sendint(msgsock, (int)VIOLATE_ALLOC));
    else return(-2);
  }

  rpd = players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]];
  if (volumes[hostcommand->parm[1]].type != RPD_DEV ||
      volumes[hostcommand->parm[1]].recordable == 0 ||
      volumes[hostcommand->parm[5]].type != RPD_DEV ||
      !(rpd->record)) {
    if (!syncval) 
      return(sendint(msgsock, (int)FUNC_NOT_SUPPORTED));
    else return(-2);
  }
  if (MAX_LOCK_TIME && hostcommand->parm[4] &&
      abs((hostcommand->parm[3] - hostcommand->parm[2]) / hostcommand->parm[4])
      > MAX_LOCK_TIME && hostcommand->parm[9] == RETURN_SYNC) {
    if (!syncval) return(sendint(msgsock,(int)SEGMENT_TOO_LONG));
    else return(-2);
  }
  /* Try to use a local resource for source, if possible, otherwise
     use closest resource */
  resource = -1;
  for (i = 0; i < volumes[hostcommand->parm[5]].num_resources; i++) {
    if (players[volumes[hostcommand->parm[5]].resource[i]]->devtype != NETRPD &&
	players[volumes[hostcommand->parm[5]].resource[i]]->devtype != NETRPD_RECORD) {
      resource = i;
      break;
    }
  }

  if (resource == -1) {
    resource = findclosetresource(hostcommand->parm[5], hostcommand->parm[6]);
  }

  if (resource == -1) {
    if (!syncval) return(sendint(msgsock, FUNC_NOT_SUPPORTED));
    return -2;
  }

  volumes[hostcommand->parm[5]].cur_resource = resource;

  srcrpd = players[volumes[hostcommand->parm[5]].resource[resource]];

  ret = (*srcrpd->search)(srcrpd, hostcommand->parm[6], 1);
  if ( ret == -1) {
    if (!syncval) return(sendint(msgsock, COULDNT_SEARCH));
    return -2;
  }
  ret = (*srcrpd->getframe)(srcrpd);
  if (ret != hostcommand->parm[6]) {
    if (!syncval) return(sendint(msgsock, COULDNT_SEARCH));
    return -2;
  }

  if (hostcommand->parm[8]) {
    sourceout = outputvolumeoutput(hostcommand->parm[5], players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]]->pseudo_out);
    ret = doswitchtree(sourceout, hostcommand->parm[8], players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]]->pseudo_out);
    if (ret == -1) {
      if (!syncval) return(sendint(msgsock, (int)COULDNT_ROUTE));
      else return(-2);
    }
  }

#ifdef OBSOLETE
  /* rpd->recordsetup now does the search in advance */
  ret = (*rpd->search)(rpd, hostcommand->parm[2], 1);
  if ( ret == -1) {
    if (!syncval) return(sendint(msgsock, COULDNT_SEARCH));
    return -2;
  }
#endif /* OBSOLETE */

  if (rpd->recordsetup) {
    ret = (*rpd->recordsetup)(rpd, hostcommand->parm[2], 
			      hostcommand->parm[3]);
    if (ret == -1) {
      if (!syncval) return(sendint(msgsock, COULDNT_DO_FUNC));
      else return -2;
    }
  }
  else {
    bsdsyslog(LOG_NOTICE, "Model %s is lacking recordsetup METHOD",
	      rpd->model);
    if (!syncval) return(sendint(msgsock, COULDNT_DO_FUNC));
    else return -2;
  }

  if (DEBUG) printf("DoDub: recording from %d to %d\n",
		    hostcommand->parm[2], hostcommand->parm[3]);
  ret = (*srcrpd->varspeed)(srcrpd, hostcommand->parm[7]);
  if (ret != -1) {
    ret = (*rpd->recordlen)(rpd, hostcommand->parm[3] - hostcommand->parm[2],
			 hostcommand->parm[4], hostcommand->parm[9]);
    if (hostcommand->parm[9] == RETURN_SYNC)
      (*srcrpd->varspeed)(srcrpd, STOP); /* Doesn't matter if failure */
  }

  if (ret != -1) {
    used_segment(rpd,hostcommand->parm[2],
		 hostcommand->parm[3]-hostcommand->parm[2]);
    record_frames = hostcommand->parm[3] - hostcommand->parm[2] + 1;
    if (cur_seglist->start == hostcommand->parm[2]) {
      /* At beginning of seg */
      if (DEBUG) {
	printf("DoDub: freeing from beginning of segment\n");
	printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
      }
      cur_seglist->start+=record_frames;
      cur_seglist->nframes-=record_frames;
      if (DEBUG) 
	printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
    }
    else if (cur_seglist->start+cur_seglist->nframes ==
	     hostcommand->parm[2] + record_frames) {
      /* At end of of seg */
      if (DEBUG) {
	printf("DoDub: freeing from end of segment\n");
	printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
      }
      cur_seglist->nframes-=record_frames;
      if (DEBUG) 
	printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
    }
    else {
      /* In middle of seg, hardest case */
      if (DEBUG) {
	printf("DoDub: freeing from middle of segment\n");
	printf("Old start = %d, old nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
      }
      temp_seglist = (RPD_SEGLIST *)calloc(1, sizeof(RPD_SEGLIST));
      if (temp_seglist == (RPD_SEGLIST *)NULL) {
	if (!syncval) return(sendint(msgsock, (int)COULDNT_FREE));
	else return(-2);
      }
      temp_seglist->start = hostcommand->parm[2]+record_frames;
      temp_seglist->nframes = cur_seglist->start+cur_seglist->nframes-
	(hostcommand->parm[2] + record_frames);
      temp_seglist->volume_id = cur_seglist->volume_id;
      temp_seglist->next = cur_seglist->next;
      cur_seglist->next = temp_seglist;
      cur_seglist->nframes = hostcommand->parm[2] - cur_seglist->start;
      if (DEBUG) {
	printf("New start = %d, new nframes = %d\n",cur_seglist->start,
	       cur_seglist->nframes);
	printf("New segment: start = %d, nframes = %d\n",
	       temp_seglist->start,
	       temp_seglist->nframes);
      }
    }
  }
  if (ret == -1) {
    if (!syncval) return(sendint(msgsock, (int)COULDNT_DO_FUNC));
    else return(-2);
  }
  if (!syncval) return(sendint(msgsock, (int)NO_ERROR));
  else return(-2);
}

/* parm 1 is dest volume
   parm 2 is source volume
   parm 3 is mask
   parm 4 is sync
*/
DoRecordPreview(msgsock, hostcommand, clinum)
     int msgsock, clinum;
     Galatea_packet *hostcommand;
{
  RPD_ptr rpd;
  Output sourceout, outputvolumeoutput();
  int ret;

  if (clients[clinum].rev != revision) {
    if (!hostcommand->parm[4]) return(sendint(msgsock, (int)VOLUME_LIST_OLD));
    else return(-2);
  }
  if (hostcommand->parm[1] >= num_volumes ||
      volumes[hostcommand->parm[1]].output != clients[clinum].output ||
      hostcommand->parm[2] >= num_volumes ||
      volumes[hostcommand->parm[2]].output != clients[clinum].output) {
    if (!hostcommand->parm[4]) return(sendint(msgsock, (int)BAD_VOLUME));
    else return(-2);
  }
  rpd = players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]];

  if (volumes[hostcommand->parm[1]].type != RPD_DEV ||
      volumes[hostcommand->parm[1]].recordable == 0) {
    if (!hostcommand->parm[4]) 
      return(sendint(msgsock, (int)FUNC_NOT_SUPPORTED));
    else return(-2);
  }

  if (hostcommand->parm[3]) {
    sourceout = outputvolumeoutput(hostcommand->parm[2], players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]]->pseudo_out);
    if (DEBUG) printf("Pseudo-out = %d\n",players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]]->pseudo_out);
    ret = doswitchtree(sourceout, hostcommand->parm[3], players[volumes[hostcommand->parm[1]].resource[volumes[hostcommand->parm[1]].cur_resource]]->pseudo_out);
    if (ret == -1) {
      if (!hostcommand->parm[4]) return(sendint(msgsock, (int)COULDNT_ROUTE));
      else return(-2);
    }
  }
  ret = (*rpd->cmd)(rpd,RECORD_MODE_ON);
  if (ret == -1) {
    if (!hostcommand->parm[4]) return(sendint(msgsock, (int)COULDNT_DO_FUNC));
    else return(-2);
  }
  if (!hostcommand->parm[4]) return(sendint(msgsock, (int)NO_ERROR));
  else return(-2);
}

Output outputvolumeoutput(whichvol, pseudoout)
     int whichvol, pseudoout;
{
  RPD_ptr rpd;
  INPUT_ptr inputter;
  
  if (volumes[whichvol].type == RPD_DEV) {
    rpd = 
      players[volumes[whichvol].resource[volumes[whichvol].cur_resource]];
    return(rpd->output_chans[rpd->outputnum[pseudoout]]);
  }
  else {
    inputter = 
      inputs[volumes[whichvol].resource[volumes[whichvol].cur_resource]];
    return(inputter->output_chans[inputter->outputnum[pseudoout]]);
  }
}

