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

build_volumes(close_previous)
     int close_previous;
{
    int i, j, intable, cur_volume = 0, cur_tvolume = 0, num_tvolumes, k;
    DeviceList *tvolumes;
    
    extctrl(EXT_PREBUILD, NULL);
    
    if (volumes) {
	free(volumes);
#ifdef TRAP_BUG
	bsdsyslog(LOG_INFO,"freed old volume table");
#endif /* TRAP_BUG */
    }
    
    revision++;
    
    clean_clients();
    
#ifdef TRAP_BUG
    bsdsyslog(LOG_INFO,"cleaned clients");
#endif /* TRAP_BUG */
    
    clear_locks();
#ifdef TRAP_BUG
    bsdsyslog(LOG_INFO,"cleared locks");
#endif /* TRAP_BUG */
    
    if (close_previous) {
	for (i = 0; i < num_players; i++)
	  rpdutil_close(players[i]);
	for (i = 0; i < num_switchers; i++) {
	    swtrutil_close(switchers[i]);
	}
	for (i = 0; i < num_forwards; i++) {
	    if (servs[i]) GCloseServer(servs[i]);
	}
	sleep(1);   /* give UNIX a bit to catch up */
    }
#ifdef TRAP_BUG
    bsdsyslog(LOG_INFO,"closed old devices");
#endif /* TRAP_BUG */
    
    for (i = 0; i < 30; i++)
      realswitcher[i] = -1;
#ifdef TRAP_BUG
    bsdsyslog(LOG_INFO,"reset realswitcher table");
#endif /* TRAP_BUG */
    
    if( vconf_get_table(configfile, &vdt ) != VCONF_AOK ) {
	volumes = NULL;
	num_volumes = 0;
	extctrl(EXT_POSTBUILD, NULL);
	return;
    }
#ifdef TRAP_BUG
    bsdsyslog(LOG_INFO,"loaded new volume table");
#endif /* TRAP_BUG */
    
    /* build volume table */
    num_switchers = 0;
    for (i = 0; i < vdt.ndevs; i++) {
	if (vdt.dev[i].type == SWTR_DEV) {
	    sscanf(vdt.dev[i].name,"SWTR-%d",&j);
	    if ((switchers[num_switchers] = swtrutil_open(&vdt,i)) == NULL) {
		bsdsyslog(LOG_INFO,"Open failed: %s, %s, at %s",
			  vdt.dev[i].model, vdt.dev[i].name, vdt.dev[i].tty);
	    }
	    else {
		bsdsyslog(LOG_INFO,"%s, %s, at %s",switchers[num_switchers]->model,
			  switchers[num_switchers]->devname, 
			  switchers[num_switchers]->port);
		realswitcher[j] = num_switchers++;
	    }
	}
    }    
    
    num_volumes = num_players = num_inputs = 0;
    for ( i = 0; i < vdt.ndevs; i++) {
	if (vdt.dev[i].type == RPD_DEV) {
	    if ((players[num_players] = rpdutil_open(&vdt, i)) == NULL) {
		bsdsyslog(LOG_INFO,"Open failed: %s, %s, at %s",
			  vdt.dev[i].model, vdt.dev[i].name, vdt.dev[i].tty);
	    }
	    else {
		bsdsyslog(LOG_INFO,"%s, %s, at %s",players[num_players]->model,
			  players[num_players]->devname, players[num_players]->port);
		for ( k = 0; k < MAXSERVEROUTS; k++) {
		    intable = 0;
		    if (players[num_players]->outputnum[k] != -1) {
			for ( j = 0; j < num_players; j++) {
			    if (!strcmp(players[num_players]->devname,
					players[j]->devname)) {
				if (players[j]->outputnum[k] != -1) intable++;
			    }
			}
			if (!intable) num_volumes++;
		    }
		}
		num_players++;
	    }
	}
	if (vdt.dev[i].type == INPUT_DEV) {
	    if ((inputs[num_inputs] = inpututil_open(&vdt, i)) == NULL) {
		bsdsyslog(LOG_INFO,"Open failed: INPUT, %s, at %s", vdt.dev[i].name,
			  vdt.dev[i].tty);
	    }
	    else {
		bsdsyslog(LOG_INFO, "INPUT, %s, at %s",
			  inputs[num_inputs]->devname, vdt.dev[i].tty);
		for ( k = 0; k < MAXSERVEROUTS; k++) {
		    intable = 0;
		    if (inputs[num_inputs]->outputnum[k] != -1) {
			for ( j = 0; j < num_inputs; j++)
			  if (!strcmp(inputs[num_inputs]->devname,
				      inputs[j]->devname)) {
			      if (inputs[j]->outputnum[k] != -1) intable++;
			  }
			if (!intable) num_volumes++;
		    }
		}
		num_inputs++;
	    }
	}
    }  
    if (DEBUG) printf("%d distinct volumes available.\n",num_volumes);
    volumes = (DeviceList *)repeat_malloc(sizeof(DeviceList)*num_volumes);
    if (volumes == NULL) {
	bsdsyslog(LOG_CRIT,
		  "Could not malloc volume table.  Self-sending SIGTERM\n");
	kill(getpid(),SIGTERM);
	sleep(99999999);
	exit(1);
    }
    cur_volume = 0;
    for (i = 0; i < num_players; i++) {
	for ( k = 0; k < MAXSERVEROUTS; k++) {
	    intable = -1;
	    if (players[i]->outputnum[k] != -1) {
		for (j = 0; j < cur_volume; j++)
		  if (!strcmp(players[i]->devname,
			      volumes[j].volume) &&
		      volumes[j].output == k &&
		      volumes[j].type == RPD_DEV)
		    intable = j;
		if (intable == -1) {
		    strcpy(volumes[cur_volume].volume,players[i]->devname);
		    volumes[cur_volume].type = RPD_DEV;
		    volumes[cur_volume].num_resources = 1;
		    volumes[cur_volume].cur_resource = 0;
		    volumes[cur_volume].output = k;
		    volumes[cur_volume].resource[0] = i;
		    if (players[i]->record) volumes[cur_volume].recordable = 1;
		    else volumes[cur_volume].recordable = 0;
		    cur_volume++;
		}
		else {/* what to do about duplicates */
		    volumes[intable].resource[volumes[intable].num_resources++] = i;
		    /* may not allow recording on volumes with multiple devices */
		    volumes[intable].recordable = 0;
		}
	    }
	}
    }
    for (i = 0; i < num_inputs; i++) {
	for ( k = 0; k < MAXSERVEROUTS; k++) {
	    intable = -1;
	    if (inputs[i]->outputnum[k] != -1) {
		for (j = 0; j < cur_volume; j++)
		  if (!strcmp(inputs[i]->devname,
			      volumes[j].volume) &&
		      volumes[j].output == k &&
		      volumes[j].type == INPUT_DEV)
		    intable = j;
		if (intable == -1) {
		    strcpy(volumes[cur_volume].volume,inputs[i]->devname);
		    volumes[cur_volume].type = INPUT_DEV;
		    volumes[cur_volume].num_resources = 1;
		    volumes[cur_volume].cur_resource = 0;
		    volumes[cur_volume].output = k;
		    volumes[cur_volume].resource[0] = i;
		    cur_volume++;
		}
		else {/* what to do about duplicates */
		    volumes[intable].resource[volumes[intable].num_resources++] = i;
		}
	    }
	}
    }
    num_tvolumes = 0;
    for ( i = 0; i < num_volumes; i++) {
	if (volumes[i].num_resources != 0) num_tvolumes++;
    }
    tvolumes = (DeviceList *)repeat_malloc(sizeof(DeviceList)*num_tvolumes);
    /* eliminate zero resource volumes if possible */
    if (tvolumes) {
	for (i = 0; i < num_volumes; i++) {
	    if (volumes[i].num_resources != 0) {
		/*	if (DEBUG) printf("volume %d is %s, %d resources, output %d\n", 
			cur_tvolume, 
			volumes[i].volume,
			volumes[i].num_resources,
			volumes[i].output);*/
		tvolumes[cur_tvolume++] = volumes[i];
	    }
	}
	if (volumes) free(volumes);
	volumes = tvolumes;
	num_volumes = num_tvolumes;
	if (DEBUG) printf("Cleaned: %d distinct volumes available.\n",num_volumes);
    }
    else {
	if (DEBUG) printf("Couldn't clean volume table for 0 resources.\n");
	/*    for (i = 0; i < num_volumes; i++)
	      if (DEBUG) printf("volume %d is %s, %d resources, output %d\n", 
	      i, 
	      volumes[i].volume,
	      volumes[i].num_resources,
	      volumes[i].output);*/
    }
    if (run_state) spinupplayers();
    unlock_all();
    restore_allocations();
    extctrl(EXT_POSTBUILD, NULL);
    return;
}

check_devices() 
{ 
  /* This should poll every device that is marked as
     operating, to make sure that it is still operating.  Cannot use
     {rpd,swtr}->reset() because the device may be in the middle of an
     operation.  Must use {rpd,swtr}->proddev().  If {rpd,swtr}->proddev()
     doesn't exist for a device, then skip it.  If a device no longer
     responds, set need_to_rebuild_list = 1; */

  /* Then it should check every device that is marked as not operating,
     to see if it is now operating.  This can use {rpd,swtr}->reset, as
     the device is not being used.  If a previously non-operabting device
     is now operating, then set need_to_rebuild_list = 1; */
}
     
