/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
#undef MAIN
#include "afni.h"
#include "afni_plugout.h"
#ifdef ALLOW_PLUGINS
/** global data for plugouts **/
static IOCHAN * ioc_control[NUM_TCP_CONTROL] ; /* 21 Nov 2001: now an array */
static char * ioc_conname[NUM_TCP_CONTROL] ;
static int npout = 0 ; /* number of plugouts allocated */
static PLUGOUT_spec ** pout = NULL ; /* malloc-ed array of plugouts */
#undef RETRY
static int verbose = 0 ; /* 28 April 1998 */
static int started = 0 ; /* 07 Nov 2001 */
/*-----------------------------------------------------------------------*/
int AFNI_have_plugouts( void ){ return started ; } /* 07 Nov 2001 */
/*-----------------------------------------------------------------------
Initialize plugouts: setup the work process
-------------------------------------------------------------------------*/
void AFNI_init_plugouts( void )
{
int cc ;
char * env ;
int base_port ;
ENTRY("AFNI_init_plugouts") ;
if( started ) EXRETURN ; /* 07 Nov 2001 */
PLUTO_register_workproc( AFNI_plugout_workproc , NULL ) ;
atexit( AFNI_plugout_exit ) ;
verbose = (GLOBAL_argopt.plugout_code & 1) != 0 ;
/* 14 Dec 2005 by JMS: allow plugout tcp ports to be overrided */
/* (put into AFNI distribution 31 Jan 2006 [rickr]) */
base_port = BASE_TCP_CONTROL;
env = getenv("AFNI_PLUGOUT_TCP_BASE");
if( env != NULL ){
base_port = atoi(env);
if( base_port < 1024 || base_port > 65535 ){ /* check for validity */
fprintf(stderr,"\nPO: bad AFNI_PLUGOUT_TCP_BASE %d,"
" should be in [%d,%d]\n", base_port, 1024, 65535);
base_port = BASE_TCP_CONTROL; /* invalid, so use default */
} else /* warn user (and use it) */
fprintf(stderr,"\nPO: applying AFNI_PLUGOUT_TCP_BASE %d (%d ports)\n",
base_port, NUM_TCP_CONTROL);
}
for( cc=0 ; cc < NUM_TCP_CONTROL ; cc++ ){ /* 21 Nov 2001: */
ioc_control[cc] = NULL ; /* initialize control */
ioc_conname[cc] = AFMALL(char, 32) ; /* sockets and names */
sprintf(ioc_conname[cc],"tcp:*:%d",base_port+cc) ;
}
started = 1 ; EXRETURN ;
}
/*-----------------------------------------------------------------------
Routine executed at AFNI exit: shutdown all plugout IOCHANs.
-------------------------------------------------------------------------*/
void AFNI_plugout_exit( void )
{
int jj , cc ;
for( cc=0 ; cc < NUM_TCP_CONTROL ; cc++ ){ /* close any open */
iochan_set_cutoff( ioc_control[cc] ) ; /* control sockets */
iochan_close ( ioc_control[cc] ) ;
}
for( jj=0 ; jj < npout ; jj++ ){ /* close any plugouts */
if( pout[jj] != NULL && pout[jj]->ioc != NULL ){
iochan_set_cutoff( pout[jj]->ioc ) ;
iochan_close ( pout[jj]->ioc ) ;
if( verbose )
fprintf(stderr,"PO: atexit closed channel from plugout %s\n",
pout[jj]->po_name ) ;
}
}
return ;
}
/*-----------------------------------------------------------------------
Plugout workprocess: listen for incoming control connections.
(If the return is True, that means don't call this workproc again.
If the return is False, that means call this workproc again.......)
-------------------------------------------------------------------------*/
#define CONTROL_BUFSIZE (16*1024)
Boolean AFNI_plugout_workproc( XtPointer elvis )
{
int jj , ngood , pcode , ii , opcount=0 , cc ;
PLUGOUT_spec * pp ;
/********************************************/
/** start up non-listening control sockets **/
AFNI_block_rescan(1) ; /* 10 Nov 2005 */
for( cc=0 ; cc < NUM_TCP_CONTROL ; cc++ ){
if( ioc_control[cc] == NULL ){ /* not open now, so open it */
ioc_control[cc] = iochan_init( ioc_conname[cc] , "accept" ) ;
#ifdef RETRY
if( ioc_control[cc] == NULL ){
if( verbose )
fprintf(stderr,"PO: waiting to listen on control channel") ;
for( ii=0 ; ii < 10 ; ii++ ){
if( verbose ) fprintf(stderr,".") ;
iochan_sleep(VLONG_DELAY) ; /* wait a bit, try again */
ioc_control[cc] = iochan_init( ioc_conname[cc] , "accept" ) ;
if( ioc_control[cc] != NULL ) break ;
}
if( verbose ) fprintf(stderr,"\n") ;
}
#endif /* RETRY */
if( ioc_control[cc] != NULL ) opcount++ ;
}
}
/****************************************/
/** see if any control socket is ready **/
for( cc=0 ; cc < NUM_TCP_CONTROL ; cc++ ){
if( ioc_control[cc] == NULL ) continue ; /* not listening */
jj = iochan_goodcheck(ioc_control[cc],SHORT_DELAY) ;
if( jj == 0 ) continue ; /* not ready */
if( jj == 1 ){ /* someone connected to the control socket! */
int npobuf ;
char * pobuf ;
/** check if the connection is trustworthy **/
fprintf(stderr,"PO: plugout connection from host %s\n",ioc_control[cc]->name) ;
if( !TRUST_host(ioc_control[cc]->name) ){
fprintf(stderr,"PO: untrusted host: %s -- connection denied\n" ,
ioc_control[cc]->name) ;
iochan_set_cutoff(ioc_control[cc]) ; IOCHAN_CLOSE(ioc_control[cc]) ;
continue ; /* skip to next control socket */
}
/** read all data possible from the control channel **/
npobuf = 0 ; /* number of bytes received so far */
pobuf = (char *) malloc( sizeof(char) * CONTROL_BUFSIZE ) ;
while(1){
jj = iochan_recv( ioc_control[cc] , pobuf+npobuf , CONTROL_BUFSIZE-npobuf ) ;
if( jj < 1 ) break ; /* stop if nothing more comes in */
npobuf += jj ;
if( npobuf >= CONTROL_BUFSIZE ){ /* stop if overflow */
fprintf(stderr,"PO: control channel buffer overflow!\n") ;
break ;
}
for( ii=0 ; ii < npobuf ; ii++ ) if( pobuf[ii] == '\0' ) break ;
if( ii < npobuf ) break ; /* stop if found a NUL character */
iochan_sleep( SHORT_DELAY ) ; /* wait for some more? */
}
if( npobuf < 1 ){
fprintf(stderr,"PO: control channel sent no data!\n") ;
iochan_set_cutoff(ioc_control[cc]) ; IOCHAN_CLOSE(ioc_control[cc]) ;
free(pobuf) ;
continue ; /* skip to next control socket */
}
/** process the input and make a new connection to a plugout program **/
pp = new_PLUGOUT_spec( npobuf , pobuf ) ;
if( pp == NULL ){
fprintf(stderr,"PO: can't create PLUGOUT_spec. Input was:\n%s\n",pobuf) ;
PO_ACK_BAD(ioc_control[cc]) ;
iochan_sleep(LONG_DELAY) ;
iochan_set_cutoff(ioc_control[cc]) ; IOCHAN_CLOSE(ioc_control[cc]) ;
free(pobuf) ;
continue ; /* skip to next control socket */
} else {
if( pp->do_ack ) PO_ACK_OK(ioc_control[cc]) ;
iochan_sleep(LONG_DELAY) ;
iochan_set_cutoff(ioc_control[cc]) ; IOCHAN_CLOSE(ioc_control[cc]) ;
fprintf(stderr,"PO: plugout connection name is %s\n",pp->po_name) ;
}
if( npout == 0 ){
pout = (PLUGOUT_spec **) malloc( sizeof(PLUGOUT_spec *) ) ;
} else {
pout = (PLUGOUT_spec **) realloc( pout , sizeof(PLUGOUT_spec *)*(npout+1) ) ;
}
pout[npout++] = pp ;
free(pobuf) ;
opcount++ ;
} else if( jj == -1 ){ /* something bad happend to control socket */
#if 0
if( verbose )
fprintf(stderr,"PO: failure while listening to control channel!\n") ;
#endif
iochan_set_cutoff(ioc_control[cc]) ; IOCHAN_CLOSE(ioc_control[cc]) ;
continue ; /* skip to next control socket */
}
} /* end of loop over control sockets */
/*****************************************************/
/** see if any of the existing plugouts sent data, **/
/** or needs to have data sent to it. **/
ngood = 0 ;
for( jj=0 ; jj < npout ; jj++ ){
if( pout[jj] != NULL ){
pcode = AFNI_process_plugout( pout[jj] ) ;
if( pcode < 0 ) DESTROY_PLUGOUT( pout[jj] ) ;
else ngood++ ;
if( pcode ) opcount++ ;
}
}
/* if all plugouts are deceased, free their array */
if( ngood == 0 && pout != NULL ){ npout = 0 ; free(pout) ; pout = NULL ; }
/* if nothing happened, take a short nap */
AFNI_block_rescan(0) ; /* 10 Nov 2005 */
if( opcount == 0 ) iochan_sleep(LONG_DELAY) ;
return(False) ;
}
/*------------------------------------------------------------------------
Process a plugout. Return codes are:
0 = nothing happened
-1 = a fatal error for this plugout --> close it down!
1 = data was sent to plugout
2 = data was received from plugout
Receiving data from a plugout has higher priority than sending
data to a plugout. Both will not occur in the same cycle.
--------------------------------------------------------------------------*/
#define PO_BUFSIZE (64*1024) /* 14 Nov 2001: expand from 16K to 64K */
#define MAX_STR 1024 /* 21 Nov 2001 */
int AFNI_process_plugout( PLUGOUT_spec * pp )
{
int ii , jj , npobuf , nend , retval=0 ;
Three_D_View * im3d ;
static char pobuf[PO_BUFSIZE+1] ; /* I/O buffer */
static char oobuf[1024] ;
int nstr ; /* 21 Nov 2001: number of substrings */
static char *str[MAX_STR] ; /* pointers to substrings from plugout */
int ss , bb,aa ;
char *spt ;
/** find the lowest numbered open controller **/
for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
im3d = GLOBAL_library.controllers[ii] ;
if( IM3D_OPEN(im3d) ) break ;
}
if( ii == MAX_CONTROLLERS ) return(0) ; /* nothing available? weird */
/** if the IOCHAN isn't ready yet, see if it has become ready **/
if( ! pp->ioc_ready ){
ii = iochan_goodcheck( pp->ioc , SHORT_DELAY ) ;
if( ii == 0 ) return( 0) ; /* still waiting */
if( ii < 0 ){ /* something bad */
fprintf(stderr,"PO: plugout %s IOCHAN failed to establish.\n",
pp->po_name ) ;
spt = iochan_error_string() ;
if( spt != NULL ) fprintf(stderr," : %s\n",spt) ;
return(-1) ;
}
pp->ioc_ready = 1 ; /* mark that it is ready */
if( verbose )
fprintf(stderr,"PO: plugout %s IOCHAN connection established.\n",
pp->po_name ) ;
}
/***************************************************/
/** See if the plugout wants to send us some data **/
jj = iochan_readcheck( pp->ioc , SHORT_DELAY ) ;
if( jj < 0 ){ /* something bad happened */
fprintf(stderr,"PO: plugout %s has broken connection!\n",pp->po_name) ;
spt = iochan_error_string() ;
if( spt != NULL ) fprintf(stderr," : %s\n",spt) ;
return(-1) ;
}
if( jj > 0 ){ /*** data is incoming: get it, and process the commands ***/
/** read the incoming data **/
npobuf = iochan_recv( pp->ioc , pobuf , PO_BUFSIZE ) ;
if( npobuf <= 0 ){ /* this error is unlikely */
fprintf(stderr,"PO: failure to read data from plugout %s!\n",pp->po_name) ;
spt = iochan_error_string() ;
if( spt != NULL ) fprintf(stderr," : %s\n",spt) ;
return(-1) ;
}
if( verbose )
fprintf(stderr,"PO: plugout %s sent %d bytes of data\n",pp->po_name,npobuf ) ;
/** ensure data is NUL terminated **/
if( pobuf[npobuf-1] != '\0' ) pobuf[npobuf++] = '\0' ;
/* 21 Nov 2001: break input into substrings (at NULs) */
ss = aa = 0 ; /* ss=substring index , aa=pobuf index at start of substring */
while( ss < MAX_STR && aa < npobuf ){
/* skip aa ahead to next non-blank, non-NUL */
for( ; aa < npobuf &&
(pobuf[aa]=='\0' || isspace(pobuf[aa])) ; aa++ ) ; /* nada */
if( aa == npobuf ) break ; /* didn't find anything */
for( bb=aa+1 ; pobuf[bb] != '\0' ; bb++ ) ; /* skip bb to next NUL */
str[ss++] = pobuf+aa ; /* point to this substring */
aa = bb+1 ; /* start at next char */
}
nstr = ss ; if( nstr > 0 ) retval = 2 ;
if( verbose && nstr > 1 )
fprintf(stderr,"PO: received %d command strings at once\n",nstr) ;
/** determine what to do with each substring **/
for( ss=0 ; ss < nstr ; ss++ ){
/* set Talairach coordinates */
if( strncmp(str[ss],"TT_XYZ_SET",10) == 0 ){
float xx , yy , zz ;
ii = sscanf( str[ss] , "TT_XYZ_SET %f %f %f" , &xx , &yy , &zz ) ;
if( ii < 3 ){
fprintf(stderr,"PO: malformed TT_XYZ_SET string from plugout %s: %s\n",
pp->po_name , str[ss] ) ;
if( pp->do_ack ) PO_ACK_BAD( pp->ioc ) ;
} else if( im3d->vinfo->view_type != VIEW_TALAIRACH_TYPE ){
fprintf(stderr,"PO: can't accept TT_XYZ_SET from plugout %s in %s\n",
pp->po_name , VIEW_typestr[im3d->vinfo->view_type]) ;
if( pp->do_ack ) PO_ACK_BAD( pp->ioc ) ;
} else { /* actually change coordinates */
if( verbose )
fprintf(stderr,"PO: command TT_XYZ_SET %g %g %g\n",xx,yy,zz) ;
jj = AFNI_jumpto_dicom( im3d , -xx,-yy,zz ) ;
if( pp->do_ack ){
if( jj < 0 ) PO_ACK_BAD( pp->ioc ) ;
else PO_ACK_OK ( pp->ioc ) ;
}
}
/* set coordinates in DICOM order */
} else if( strncmp(str[ss],"DICOM_XYZ_SET",13) == 0 ){
float xx , yy , zz ;
ii = sscanf( str[ss] , "DICOM_XYZ_SET %f %f %f" , &xx , &yy , &zz ) ;
if( ii < 3 ){
fprintf(stderr,"PO: malformed DICOM_XYZ_SET string from plugout %s: %s\n",
pp->po_name , str[ss] ) ;
if( pp->do_ack ) PO_ACK_BAD( pp->ioc ) ;
} else { /* actually set coordinates */
if( verbose )
fprintf(stderr,"PO: command DICOM_XYZ_SET %g %g %g\n",xx,yy,zz) ;
jj = AFNI_jumpto_dicom( im3d , xx,yy,zz ) ;
if( pp->do_ack ){
if( jj < 0 ) PO_ACK_BAD( pp->ioc ) ;
else PO_ACK_OK ( pp->ioc ) ;
}
}
/* set voxel indexes */
} else if( strncmp(str[ss],"DSET_IJK_SET",12) == 0 ){
int ix , jy , kz ;
ii = sscanf( str[ss] , "DSET_IJK_SET %d %d %d" , &ix , &jy , &kz ) ;
if( ii < 3 ){
fprintf(stderr,"PO: malformed DSET_IJK_SET string from plugout %s: %s\n",
pp->po_name , str[ss] ) ;
if( pp->do_ack ) PO_ACK_BAD( pp->ioc ) ;
} else { /* actually set indexes */
if( verbose )
fprintf(stderr,"PO: command DSET_IJK_SET %d %d %d\n",ix,jy,kz) ;
AFNI_set_viewpoint( im3d , ix,jy,kz , REDISPLAY_ALL ) ;
if( pp->do_ack ) PO_ACK_OK ( pp->ioc ) ;
}
/* send voxel indexes back to plugout */
} else if( strncmp(str[ss],"DSET_IJK_GET",12) == 0 ){
int ix=im3d->vinfo->i1 , jy=im3d->vinfo->j2 , kz=im3d->vinfo->k3 ;
if( verbose )
fprintf(stderr,"PO: command DSET_IJK_GET -> %d %d %d\n",ix,jy,kz) ;
sprintf(oobuf,"DSET_IJK %d %d %d\n" , ix,jy,kz ) ; /* send result */
PO_SEND( pp->ioc , oobuf ) ;
if( pp->do_ack ){
jj = iochan_readcheck( pp->ioc, -1 ) ; /* wait for return message */
if( jj == -1 ) return(-1) ; /* something bad! */
jj = iochan_recv( pp->ioc , oobuf , POACKSIZE ) ; /* read message */
if( verbose )
fprintf(stderr, (jj > 0) ? "PO: received acknowledgment\n"
: "PO: did not receive acknowledgment\n" ) ;
}
/* set surface node ID */
} else if( strncmp(str[ss],"SURFID",6) == 0 ){
if( SUMA_ENABLED && SESSION_HAS_SUMA(im3d->ss_now) ){
int id ;
ii = sscanf( str[ss] , "SURFID %d" , &id ) ;
if( ii < 1 ){
fprintf(stderr,"PO: malformed SURFID string from plugout %s: %s\n",
pp->po_name , str[ss] ) ;
if( pp->do_ack ) PO_ACK_BAD( pp->ioc ) ;
} else { /* find the node and jump to that location */
if( verbose )
fprintf(stderr,"PO: command SURFID %d\n",id) ;
ii = SUMA_find_node_id( im3d->ss_now->su_surf[0] , id ) ;
if( ii < 0 ){
fprintf(stderr,"PO: unknown SURFID node number %d\n",id) ;
if( pp->do_ack ) PO_ACK_BAD( pp->ioc ) ;
} else {
AFNI_jumpto_dicom( im3d ,
im3d->ss_now->su_surf[0]->ixyz[ii].x ,
im3d->ss_now->su_surf[0]->ixyz[ii].y ,
im3d->ss_now->su_surf[0]->ixyz[ii].z ) ;
if( pp->do_ack ) PO_ACK_OK ( pp->ioc ) ;
}
}
}
/*-- 07 Nov 2001: drive various AFNI user interface widgets --*/
} else if( strncmp(str[ss],"DRIVE_AFNI",10) == 0 ){
char cmd[PLUGOUT_COM_LENGTH]="\0" ;
if( strlen(str[ss]) < 11 ){
fprintf(stderr,"PO: DRIVE_AFNI from plugout %s lacks command\n",
pp->po_name ) ;
if( pp->do_ack ) PO_ACK_BAD( pp->ioc ) ;
} else { /* the command is everything after "DRIVE_AFNI " */
MCW_strncpy(cmd,str[ss]+11,PLUGOUT_COM_LENGTH) ;
if( verbose )
fprintf(stderr,"PO: command DRIVE_AFNI %s\n",cmd) ;
ii = AFNI_driver( cmd ) ; /* just do it */
if( pp->do_ack ){
if( ii < 0 ) PO_ACK_BAD( pp->ioc ) ;
else PO_ACK_OK ( pp->ioc ) ;
}
}
/*-- unknown plugout command: drop a daisy cutter on them --*/
} else {
fprintf(stderr,"PO: plugout %s sent unknown command string: %s\n",
pp->po_name , str[ss] ) ;
if( pp->do_ack ) PO_ACK_BAD( pp->ioc ) ;
}
} /* 21 Nov 2001: end of loop over substrings */
} else { /* no data incoming; maybe send something? */
/****************************************************************/
/** see if anything that has changed that we should tell about **/
npobuf = 0 ;
pobuf[0] = '\0' ;
#define FEQ(a,b) (fabs((a)-(b)) < 0.01)
/** check each output mode, and format output string if needed **/
for( ii=0 ; ii < pp->npomode ; ii++ ){
switch( pp->pomode[ii] ){
case POMODE_DICOM_XYZ_DELTA:{
float xx , yy , zz ;
xx = im3d->vinfo->xi ;
yy = im3d->vinfo->yj ;
zz = im3d->vinfo->zk ;
if( !FEQ(xx,pp->xi) || !FEQ(yy,pp->yj) || !FEQ(zz,pp->zk) )
sprintf( pobuf + npobuf , "DICOM_XYZ %9.3f %9.3f %9.3f\n" , xx,yy,zz ) ;
}
break ;
case POMODE_TT_XYZ_DELTA:{
float xx , yy , zz ;
xx = im3d->vinfo->xi ;
yy = im3d->vinfo->yj ;
zz = im3d->vinfo->zk ;
if( im3d->vinfo->view_type == VIEW_TALAIRACH_TYPE &&
(!FEQ(xx,pp->xi) || !FEQ(yy,pp->yj) || !FEQ(zz,pp->zk)) )
sprintf( pobuf + npobuf , "TT_XYZ %9.3f %9.3f %9.3f\n" , -xx,-yy,zz ) ;
}
break ;
case POMODE_DSET_IJK_DELTA:{
int ix , jy , kz ;
ix = im3d->vinfo->i1 ;
jy = im3d->vinfo->j2 ;
kz = im3d->vinfo->k3 ;
if( ix != pp->ix || jy != pp->jy || kz != pp->kz )
sprintf( pobuf + npobuf , "DSET_IJK %d %d %d\n" , ix,jy,kz ) ;
}
break ;
/* 11 Sep 2002 */
case POMODE_UNDERLAY_DELTA:{
if( !EQUIV_DSETS(pp->dset_underlay,im3d->anat_now) &&
ISVALID_DSET(im3d->anat_now) ){
sprintf( pobuf + npobuf , "UNDERLAY %s\n" ,
DSET_HEADNAME(im3d->anat_now) ) ;
}
}
break ;
case POMODE_OVERLAY_DELTA:{
if( !EQUIV_DSETS(pp->dset_overlay,im3d->fim_now) &&
ISVALID_DSET(im3d->fim_now) ){
sprintf( pobuf + npobuf , "OVERLAY %s\n" ,
DSET_HEADNAME(im3d->fim_now) ) ;
}
}
break ;
} /* end of switch on modes */
npobuf = strlen( pobuf ) ;
}
/** send string, if any, then wait for acknowledgement **/
if( npobuf > 0 ){
if( verbose )
fprintf(stderr,"PO: sending plugout %s this string:\n %s",
pp->po_name , pobuf ) ;
PO_SEND( pp->ioc , pobuf ) ; /* send */
if( pp->do_ack ){
jj = iochan_readcheck( pp->ioc, -1 ) ; /* wait for return message */
if( jj == -1 ) return(-1) ; /* something bad! */
jj = iochan_recv( pp->ioc , pobuf , POACKSIZE ) ; /* read message */
if( verbose )
fprintf(stderr, (jj > 0) ? "PO: received acknowledgment\n"
: "PO: did not receive acknowledgment\n" ) ;
}
retval = 1 ;
}
} /* end of potentially sending stuff to the plugout */
/******************************************/
/** Load memory of the current situation **/
Proust:
pp->xi = im3d->vinfo->xi ;
pp->yj = im3d->vinfo->yj ;
pp->zk = im3d->vinfo->zk ;
pp->ix = im3d->vinfo->i1 ;
pp->jy = im3d->vinfo->j2 ;
pp->kz = im3d->vinfo->k3 ;
pp->time_index = im3d->vinfo->time_index ;
pp->view_type = im3d->vinfo->view_type ;
pp->sess_num = im3d->vinfo->sess_num ;
pp->anat_num = im3d->vinfo->anat_num ;
pp->func_num = im3d->vinfo->func_num ;
pp->func_threshold = im3d->vinfo->func_threshold ;
pp->dset_underlay = im3d->anat_now ;
pp->dset_overlay = im3d->fim_now ;
return(retval) ;
}
/*------------------------------------------------------------------------
Create a new plugout,
based on the control information in the buf string.
--------------------------------------------------------------------------*/
#define STARTER(st) (strncmp(buf,st,strlen(st)) == 0)
#define NBUF 256
PLUGOUT_spec * new_PLUGOUT_spec( int ninfo , char * info )
{
PLUGOUT_spec * pp ;
char buf[NBUF] ;
char opt[32] ;
int ii , jj , nstart,nend , nuse , nbuf ;
ENTRY("new_PLUGOUT_spec") ;
/** check input for OK-osity **/
if( ninfo <= 0 ) RETURN( NULL ) ;
for( nend=0 ; nend < ninfo && info[nend] != '\0' ; nend++ ) ; /* nada */
if( nend == ninfo ){
fprintf(stderr,"PO: control string not NUL-terminated!\n") ;
RETURN( NULL ) ;
}
/** initialize a new plugout specification **/
pp = (PLUGOUT_spec *) malloc( sizeof(PLUGOUT_spec) ) ;
pp->npomode = 0 ;
pp->ioc_name[0] = '\0' ;
pp->ioc = NULL ;
strcpy(pp->po_name,"Old One-Eyed Dogface") ;
pp->do_ack = 1 ; /* 06 Sep 2001 */
if( verbose )
fprintf(stderr,"PO: initializing new plugout -- got %d input bytes\n",nend) ;
/** the input buffer should be of the form:
IO_KEYWORD options
IO_KEYWORD options
...
IOCHAN iochan_specification
where IO_KEYWORD specifies the type of
input/output will be going from/to this plugout program. **/
/******************************************/
/** Scan ahead until next command string **/
nstart = 0 ;
while( nstart < nend ){
/** skip whitespace **/
for( ; nstart < nend && isspace(info[nstart]) ; nstart++ ) ; /* nada */
if( nstart >= nend ) break ;
/** copy characters into buf until the next '\n' or '\0' **/
for( nbuf=0,jj=nstart ; nbuf < NBUF && info[jj] != '\n' && info[jj] != '\0' ; ){
buf[nbuf++] = info[jj++] ;
}
if( nbuf == NBUF ){
fprintf(stderr,"PO: line buffer overflow in control information!\n") ;
nbuf-- ;
}
buf[nbuf] = '\0' ; nstart = jj ;
/************************************/
/*** Scan for legal input strings ***/
if( verbose )
fprintf(stderr,"PO: initializer command = %s\n",buf) ;
if( STARTER("TT_XYZ_DELTA") ){
pp->pomode[ pp->npomode ] = POMODE_TT_XYZ_DELTA ;
pp->npomode ++ ;
} else if( STARTER("DICOM_XYZ_DELTA") ){
pp->pomode[ pp->npomode ] = POMODE_DICOM_XYZ_DELTA ;
pp->npomode ++ ;
} else if( STARTER("DSET_IJK_DELTA") ){
pp->pomode[ pp->npomode ] = POMODE_DSET_IJK_DELTA ;
pp->npomode ++ ;
} else if( STARTER("SURFID_DELTA") ){ /* 05 Sep 2001 */
pp->pomode[ pp->npomode ] = POMODE_SURFID_DELTA ;
pp->npomode ++ ;
} else if( STARTER("UNDERLAY_DELTA") ){ /* 11 Jan 2002 */
pp->pomode[ pp->npomode ] = POMODE_UNDERLAY_DELTA ;
pp->npomode ++ ;
} else if( STARTER("OVERLAY_DELTA") ){
pp->pomode[ pp->npomode ] = POMODE_OVERLAY_DELTA ;
pp->npomode ++ ;
} else if( STARTER("NO_ACK") ){ /* 06 Sep 2001 */
pp->do_ack = 0 ;
} else if( STARTER("IOCHAN") ){
int kk ;
sscanf( buf , "IOCHAN %127s" , pp->ioc_name ) ;
for( kk=0 ; kk < 10 ; kk++ ){
pp->ioc = iochan_init( pp->ioc_name , "accept" ) ;
if( pp->ioc != NULL ) break ;
iochan_sleep(VLONG_DELAY) ; /* wait a bit, try again */
}
if( pp->ioc == NULL )
pp->ioc = iochan_init( pp->ioc_name , "accept" ) ; /* last try */
if( pp->ioc == NULL )
fprintf(stderr,"PO: can't listen on IOCHAN %s\n",pp->ioc_name) ;
pp->ioc_ready = 0 ;
} else if( STARTER("PONAME") ){
sscanf( buf , "PONAME %127s" , pp->po_name ) ;
} else {
fprintf(stderr,"PO: illegal control info=%s\n",buf) ;
}
} /* end of loop over command buffers */
/****************************************/
/** check that something good happened **/
if( pp->ioc == NULL ){
fprintf(stderr,"PO: no IOCHAN connection established.\n") ;
free(pp) ; RETURN( NULL ) ;
}
/** initialize memory of things past **/
pp->xi = pp->yj = pp->zk = -987.654 ;
pp->time_index = -1 ;
pp->view_type = -1 ;
pp->sess_num = pp->anat_num = pp->func_num = -1 ;
pp->func_threshold = -0.987654 ;
pp->dset_underlay = pp->dset_overlay = NULL ; /* 11 Jan 2002 */
if( verbose )
fprintf(stderr,"PO: initialization completed successfully.\n") ;
RETURN( pp ) ;
}
/*************************************************************************/
#else /* ALLOW_PLUGINS not defined */
void AFNI_init_plugouts( void ){ return ; }
int AFNI_have_plugouts( void ){ return 0 ; } /* 07 Nov 2001 */
#endif /* ALLOW_PLUGINS */
syntax highlighted by Code2HTML, v. 0.9.1