Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

plugout_surf.c

Go to the documentation of this file.
00001 /***************************************************************
00002   Sample plugout program to send/receive node id's to AFNI
00003 ****************************************************************/
00004 
00005 /***** Header file for communication routines *****/
00006 
00007 #include "thd_iochan.h"
00008 
00009 /***** Global variable determining on which system AFNI runs.  *****/
00010 /***** [default is the current system, can be changed by user] *****/
00011 
00012 static char afni_host[128] = "." ;
00013 static char afni_name[128] = "\0" ;
00014 static int  afni_port      = 8019 ;
00015 static int  afni_verbose   = 0 ;  /* print out debug info? */
00016 
00017 /***** Prototypes *****/
00018 
00019 int afni_io(void) ;     /* talk to AFNI */
00020 
00021 int got_key(char *) ;   /* keyboard functions (at end of file) */
00022 void setup_key(void) ;
00023 void restore_key(void) ;
00024 
00025 /*===================================================================
00026    Main program:
00027      Read command line for options
00028      Call afni_io routine forever, and ever, and ever, and ...
00029 =====================================================================*/
00030 
00031 int main( int argc , char * argv[] )
00032 {
00033    int narg , ii ;
00034 
00035    /***** See if the pitiful user wants help *****/
00036 
00037    if( argc == 2 && strncmp(argv[1],"-help",5) == 0 ){
00038       printf("Usage: plugout_surf [-host name] [-v]\n"
00039              "This program connects to AFNI and sends/gets surface\n"
00040              "node IDs to control/know the AFNI viewpoint.\n\n"
00041              "Options:\n"
00042              "  -host name  Means to connect to AFNI running on the\n"
00043              "                computer 'name' using TCP/IP.  The default is to\n"
00044              "                connect on the current host using shared memory.\n"
00045              "  -v          Verbose mode.\n"
00046              "  -port pp    Use TCP/IP port number 'pp'.  The default is\n"
00047              "                8019, but if two plugouts are running on the\n"
00048              "                same computer, they must use different ports.\n"
00049              "  -name sss   Use the string 'sss' for the name that AFNI assigns\n"
00050              "                to this plugout.  The default is something stupid.\n"
00051             ) ;
00052       exit(0) ;
00053    }
00054 
00055    /***** Process command line options *****/
00056 
00057    narg = 1 ;
00058    while( narg < argc ){
00059 
00060       /** -host name **/
00061 
00062       if( strncmp(argv[narg],"-host",5) == 0 ){
00063          narg++ ;
00064          if( narg >= argc ){
00065             fprintf(stderr,"-host needs a following name!\a\n"); exit(1);
00066          }
00067          strcpy( afni_host , argv[narg] ) ;
00068          narg++ ; continue ;
00069       }
00070 
00071       /** -name sss **/
00072 
00073       if( strncmp(argv[narg],"-name",5) == 0 ){
00074          narg++ ;
00075          if( narg >= argc ){
00076             fprintf(stderr,"-name needs a following string!\a\n"); exit(1);
00077          }
00078          strcpy( afni_name , argv[narg] ) ;
00079          narg++ ; continue ;
00080       }
00081 
00082       /** -v **/
00083 
00084       if( strncmp(argv[narg],"-v",2) == 0 ){
00085          afni_verbose = 1 ;
00086          narg++ ; continue ;
00087       }
00088 
00089       /** -port pp **/
00090 
00091       if( strncmp(argv[narg],"-port",4) == 0 ){
00092          narg++ ;
00093          if( narg >= argc ){
00094             fprintf(stderr,"-port needs a following argument!\a\n"); exit(1);
00095          }
00096          afni_port = strtol( argv[narg] , NULL , 10 ) ;
00097          if( afni_port <= 0 ){
00098             fprintf(stderr,"-port needs a positive argument!\a\n"); exit(1);
00099          }
00100          if( strcmp(afni_host,".") == 0 ) strcpy(afni_host,"localhost") ;
00101          narg++ ; continue ;
00102       }
00103 
00104       /** Je ne sais pas **/
00105 
00106       fprintf(stderr,"Unrecognized option: %s\a\n",argv[narg]) ;
00107       exit(1) ;
00108    }
00109 
00110    /***** Loop and check in with AFNI every 100 msec *****/
00111 
00112    while( 1 ){
00113       ii = afni_io() ;      /* commune with AFNI  */
00114       if( ii < 0 ) break ;  /* bad trip? then die */
00115       iochan_sleep(100) ;   /* perchance to dream */
00116    }
00117 
00118    restore_key() ; exit(0) ;
00119 }
00120 
00121 /*===================================================================
00122   This routine handles all communications with AFNI.
00123   The only input is the global variable afni_host, which determines
00124   on which system AFNI is running.
00125   The output is -1 if an error occured, 0 if everything is OK.
00126 =====================================================================*/
00127 
00128 /***** Mode flags for determining what afni_io does.
00129        The routine progress through 5 stages:
00130 
00131        1) Open a control connection to AFNI;
00132      then
00133        2) Wait until AFNI also opens the control connection;
00134      then
00135        3) Send a control string to AFNI saying what kind of
00136             information we want, wait for an acknowledgment,
00137             close the control connection, and open a data
00138             connection to AFNI;
00139      then
00140        4) Wait for AFNI to also open the data connection;
00141      then
00142        5) Send data to AFNI or receive data from AFNI!      *****/
00143 
00144 #define AFNI_OPEN_CONTROL_MODE  1  /* 1st time thru: open control channel */
00145 #define AFNI_WAIT_CONTROL_MODE  2  /* wait for AFNI to open control chan  */
00146 #define AFNI_OPEN_DATA_MODE     3  /* now can open data channel to AFNI   */
00147 #define AFNI_WAIT_DATA_MODE     4  /* waiting for AFNI to open data chan  */
00148 #define AFNI_CONTINUE_MODE      5  /* at last! data channel is ready!     */
00149 
00150 /***** macros to send acknowledgement strings to AFNI *****/
00151 
00152 #define POACKSIZE       4  /* length of acknowledgement strings */
00153 
00154 #define PO_ACK_BAD(ic)  iochan_sendall( (ic) , "BAD" , POACKSIZE )
00155 #define PO_ACK_OK(ic)   iochan_sendall( (ic) , "OK!" , POACKSIZE )
00156 #define PO_SEND(ic,str) iochan_sendall( (ic) , (str) , strlen((str))+1 )
00157 
00158 int afni_io(void)
00159 {
00160    static int afni_mode = AFNI_OPEN_CONTROL_MODE ;  /* status variable */
00161    static IOCHAN * afni_ioc = NULL ;                /* connection to AFNI */
00162    int ii ;
00163    int need_setup_key=1 ;
00164 
00165    /***************************************************************/
00166    /***** Check to see if status is OK before we proceed.     *****/
00167    /***** (if an error occurs below, afni_mode gets set to 0) *****/
00168 
00169    if( afni_mode <= 0 ) return -1 ;
00170 
00171    /***********************************************************************/
00172    /***** First time into this routine?  Open control channel to AFNI *****/
00173 
00174    if( afni_mode == AFNI_OPEN_CONTROL_MODE ){
00175       char afni_iocname[128] ;           /* will hold name of I/O channel */
00176 
00177       /** Note that the control channel is always a
00178           TCP/IP channel to port # 7955 on the AFNI host system **/
00179 
00180       if( strcmp(afni_host,".") == 0 )
00181          sprintf( afni_iocname , "tcp:%s:7955" , "localhost" ); /* make name */
00182       else
00183          sprintf( afni_iocname , "tcp:%s:7955" , afni_host ) ;  /* make name */
00184 
00185       afni_ioc = iochan_init( afni_iocname , "create" ) ;    /* create it */
00186       if( afni_ioc == NULL ){
00187          fprintf(stderr,
00188                  "Can't create control channel %s to AFNI!\n",afni_iocname) ;
00189          afni_mode = 0 ;
00190          return -1 ;
00191       }
00192       afni_mode = AFNI_WAIT_CONTROL_MODE ; /* waiting for AFNI connection */
00193       if( afni_verbose )
00194          fprintf(stderr,"AFNI control channel created\n") ;
00195    }
00196 
00197    /****************************************************/
00198    /**** Check if AFNI control channel is connected ****/
00199 
00200    if( afni_mode == AFNI_WAIT_CONTROL_MODE ){
00201       ii = iochan_writecheck( afni_ioc , 5 ) ;     /* wait at most 5 msec */
00202 
00203       /** the iochan_*check() routines return
00204              -1 for an error,
00205               0 if not ready,
00206              >0 if the I/O channel is ready. **/
00207 
00208       if( ii < 0 ){
00209          fprintf(stderr,"Control channel to AFNI failed!\a\n") ;
00210          IOCHAN_CLOSE(afni_ioc) ;
00211          afni_mode = 0 ;
00212          return -1 ;
00213       } else if( ii > 0 ){
00214          afni_mode = AFNI_OPEN_DATA_MODE ;        /* prepare to send data */
00215          if( afni_verbose )
00216             fprintf(stderr,"AFNI control channel connected\n");
00217       } else {
00218          return 0 ;                                /* try again next time */
00219       }
00220    }
00221 
00222    /**********************************************************/
00223    /**** Send control data to AFNI, and open data channel ****/
00224 
00225    if( afni_mode == AFNI_OPEN_DATA_MODE ){
00226       char afni_iocname[128] ;
00227       char afni_buf[256] ;
00228 
00229       /** decide name of data channel:
00230             use shared memory (shm:) on ".",
00231             use TCP/IP (tcp:) on other computer systems;
00232         * Note that the TCP/IP port number can be
00233            anything that isn't already in use;
00234         * Note that the shm control name (here "surf_plugout")
00235            is a string that will be converted to an IPC
00236            key (in function string_to_key in iochan.c).       **/
00237 
00238       if( strcmp(afni_host,".") == 0 )
00239          strcpy( afni_iocname , "shm:surf_plugout:1K+1K" ) ;
00240       else
00241          sprintf( afni_iocname , "tcp:%s:%d" , afni_host , afni_port ) ;
00242 
00243       /** write the command to AFNI into the buffer:
00244             * each command ends with a newline character,
00245                 except (possibly) the last command;
00246             * the command buffer is a C string, which ends
00247                 with an ASCII NUL character;
00248             * PONAME means 'use this string for informative messages';
00249             * IOCHAN means 'use this I/O channel from now on'. **/
00250 
00251       if( afni_name[0] == '\0' ) strcpy(afni_name,"SurfaceHack") ;
00252 
00253       sprintf( afni_buf , "SURFID_DELTA\n"
00254                           "NO_ACK\n"
00255                           "PONAME %s\n"
00256                           "IOCHAN %s" ,
00257                afni_name , afni_iocname ) ;
00258 
00259       if( afni_verbose )
00260          fprintf(stderr,"Sending control information to AFNI\n") ;
00261 
00262       /** note that the ASCII NUL at the end of the buffer is sent **/
00263 
00264       ii = iochan_sendall( afni_ioc , afni_buf , strlen(afni_buf)+1 ) ;
00265 
00266       /** the return value is the number of bytes sent,
00267           or -1 indicating a fatal error transpired.    **/
00268 
00269       if( ii < 0 ){
00270          fprintf(stderr,"Transmission of control data to AFNI failed!\a\n") ;
00271          IOCHAN_CLOSE(afni_ioc) ;
00272          afni_mode = 0 ;
00273          return -1 ;
00274 
00275       } else {  /* things are cool, real cool */
00276 
00277          /** close channel **/
00278 
00279          IOCHAN_CLOSE(afni_ioc) ;
00280 
00281          /** now open data channel to AFNI **/
00282 
00283          afni_ioc = iochan_init( afni_iocname , "create" ) ;
00284          if( afni_ioc == NULL ){
00285             fprintf(stderr,
00286                     "Can't open data channel %s to AFNI!\a\n",afni_iocname) ;
00287             afni_mode = 0 ;
00288             return -1 ;
00289          } else {
00290             afni_mode = AFNI_WAIT_DATA_MODE ;
00291             if( afni_verbose ) fprintf(stderr,"AFNI data channel created\n") ;
00292          }
00293       }
00294    }
00295 
00296    /****************************************************/
00297    /***** See if data channel is connected to AFNI *****/
00298 
00299    if( afni_mode == AFNI_WAIT_DATA_MODE ){
00300 
00301       ii = iochan_goodcheck( afni_ioc , 5 ) ;  /* wait at most 5 msec */
00302       if( ii < 0 ){
00303          fprintf(stderr,
00304                  "AFNI data channel aborted before any data was sent!\a\n") ;
00305          IOCHAN_CLOSE( afni_ioc ) ;
00306          afni_mode = 0 ;
00307          return -1 ;
00308       } else if( ii > 0 ){                     /* ready to go! */
00309          afni_mode = AFNI_CONTINUE_MODE ;
00310          if( afni_verbose ) fprintf(stderr,"AFNI data channel is open\n") ;
00311          printf("\rEnter node ID: "); fflush(stdout);
00312       } else {
00313          return 0 ;                            /* try again next time */
00314       }
00315    }
00316 
00317    /**************************************************************/
00318    /***** The "normal" state of affairs:  AFNI is connected. *****/
00319    /***** See if the user wants to send node ID to AFNI,     *****/
00320    /***** or if AFNI has sent a node ID back to us.          *****/
00321 
00322 #define BUF 256
00323 
00324    if( afni_mode == AFNI_CONTINUE_MODE ){
00325       static char kbuf[BUF] ;  /* input keystroke buffer */
00326       static int  nkey=0 ;     /* number of keys */
00327       char afni_buf[BUF] ;     /* text to send to AFNI */
00328       int  id ;                /* Surface node ID code */
00329 
00330       if( need_setup_key ){ setup_key(); need_setup_key = 0; }
00331 
00332       /* see if AFNI sent anything */
00333 
00334       ii = iochan_readcheck( afni_ioc , 0 ) ;  /* don't wait */
00335 
00336       /** ii <  0  ==>  a fatal error has happened
00337           ii == 0  ==>  no data is ready
00338           ii >  0  ==>  data is ready to read from the channel **/
00339 
00340       if( ii < 0 ){        /** bad news on the I/O front **/
00341 
00342          fprintf(stderr,"\nAFNI data channel aborted!\a\n") ;
00343          IOCHAN_CLOSE(afni_ioc) ;
00344          afni_mode = 0 ;
00345          return -1 ;
00346 
00347       } else if( ii > 0 ){ /** at this point, data is incoming from AFNI **/
00348 
00349          ii = iochan_recv( afni_ioc , afni_buf , BUF ) ; /* get data */
00350 
00351          if( ii <= 0 ){    /** receive failed? */
00352             fprintf(stderr,"\nAFNI data channel recv failed!\a\n") ;
00353             IOCHAN_CLOSE(afni_ioc) ;
00354             afni_mode = 0 ;
00355             return -1 ;
00356          }
00357 
00358          /** at last! "process" the data from AFNI
00359                       (in this case, just print it out) **/
00360 
00361 #if 1
00362          printf("AFNI sent: %s\n",afni_buf) ;
00363 #else
00364          ii = sscanf( afni_buf , "SURFID %d" , &id ) ;  /* extract node id */
00365          if( ii < 1 ){
00366             fprintf(stderr,"AFNI sent bad data: %s\a\n",afni_buf) ;
00367          } else {
00368             fprintf(stderr,"AFNI sent id: %d\n",id) ;
00369          }
00370 #endif
00371 
00372          /* give prompt for keyboard input again
00373             (if had keyboard input, it will be thrown away now) */
00374 
00375          printf("\rEnter node ID: "); fflush(stdout); nkey = 0;
00376 
00377       } /* end of processing input from AFNI */
00378 
00379       /*-- check for user input --*/
00380 
00381       while( got_key(kbuf+nkey) ){ /* loop while we have keystrokes */
00382 
00383          if( isdigit(kbuf[nkey]) ){                    /* save numerals */
00384 
00385             printf("%c",kbuf[nkey++]); fflush(stdout);
00386 
00387          } else if( nkey > 0 && kbuf[nkey] == '\n' ){  /* end of string */
00388 
00389             printf("\n"); fflush(stdout); kbuf[nkey++]='\0'; break;
00390 
00391          }
00392 
00393          if( nkey == BUF ){                            /* stupid user */
00394             fprintf(stderr,"\nBad boy.\n\a"); exit(1);
00395          }
00396       }
00397 
00398       /* check if we have a whole string;
00399          if not, return; otherwise, send index to AFNI */
00400 
00401       if( nkey == 0 || kbuf[nkey-1] != '\0' ) return 0 ; /* incomplete */
00402 
00403       id = strtol( kbuf , NULL , 10 ) ;
00404       sprintf(afni_buf,"SURFID %d",id) ;
00405       ii = iochan_sendall( afni_ioc , afni_buf , strlen(afni_buf)+1 ) ;
00406 
00407       if( ii < 0 ){   /* send failed */
00408          fprintf(stderr,"AFNI data channel aborted!\a\n") ;
00409          IOCHAN_CLOSE(afni_ioc) ;
00410          afni_mode = 0 ;
00411          return -1 ;
00412       }
00413 
00414       printf("\rEnter node ID: "); fflush(stdout); nkey = 0;
00415       return 0 ;
00416    }
00417 
00418    return 0 ;
00419 }
00420 
00421 /*****************************************************************************/
00422 
00423 #include <errno.h>
00424 #include <stdlib.h>
00425 #include <strings.h>
00426 #include <curses.h>
00427 
00428 /*****************************************************************************/
00429 
00430 void setup_key(void)
00431 {
00432   stdscr = initscr();    /* Initialise curses library */
00433   noecho();              /* Turn off echo of keypresses to screen */
00434   cbreak();              /* Set terminal to one-character-at-a-time mode */
00435   nodelay(stdscr, TRUE); /* Set keyboard to no-delay mode */
00436 }
00437 
00438 /*****************************************************************************/
00439 
00440 void restore_key(void)
00441 {
00442   nodelay(stdscr, FALSE); /* Set keyboard to normal (blocking) mode */
00443   nocbreak();             /* Set terminal to "wait until press return" buffer mode */
00444   echo();                 /* Restore echo of keypresses to screen */
00445   endwin();               /* Close down curses library */
00446 }
00447 
00448 /*****************************************************************************/
00449 /* This function returns TRUE if a key has been pressed, FALSE otherwise.    */
00450 /* If a key has been pressed, it is put in the supplied pointer location.    */
00451 /*****************************************************************************/
00452 
00453 int got_key(char *char_pressed)
00454 {
00455   int return_code = 0;
00456   *char_pressed = getch();
00457   if (*char_pressed != ERR) return_code = TRUE;
00458   return(return_code);
00459 }
 

Powered by Plone

This site conforms to the following standards: