Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

writeedf.c

Go to the documentation of this file.
00001 /*
00002 NeuroServer 
00003  
00004 A collection of programs to translate between EEG data and TCP network
00005 messages. This is a part of the OpenEEG project, see http://openeeg.sf.net
00006 for details.
00007     
00008 Copyright (C) 2003, 2004 Rudi Cilibrasi (cilibrar@ofb.net)
00009      
00010 This library is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU Lesser General Public
00012 License as published by the Free Software Foundation; either
00013 version 2.1 of the License, or (at your option) any later version.
00014          
00015 This library is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 Lesser General Public License for more details.
00019              
00020 You should have received a copy of the GNU Lesser General Public
00021 License along with this library; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00023 */
00024                 
00025 
00026 
00027 #include <assert.h>
00028 #include <openedf.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <sys/time.h>
00032 #include <pctimer.h>
00033 #include <ctype.h>
00034 #include <nsutil.h>
00035 #include <nsnet.h>
00036 
00037 const char *helpText =
00038 "writeedf   v 0.34 by Rudi Cilibrasi\n"
00039 "\n"
00040 "Usage:  writeedf [options] <filename>\n"
00041 "\n"
00042 "        -p port          Port number to use (default 8336)\n"
00043 "        -n hostname      Host name of the NeuroCaster server to connect to\n"
00044 "                         (this defaults to 'localhost')\n"
00045 "        -s <num>         Only record this many seconds.\n"
00046 "                         (default is to record until interrupted)\n"
00047 "        -e <intnum>      Integer ID specifying which EEG to log (default: 0)\n"
00048 "The filename specifies the new EDF file to create.\n"
00049 ;
00050 
00051 #define MINLINELENGTH 4
00052 #define DELIMS " \r\n"
00053 
00054 struct Options {
00055         char hostname[MAXLEN];
00056         unsigned short port;
00057         char filename[MAXLEN];
00058         int eegNum;
00059         int isFilenameSet;
00060         int isLimittedTime;
00061         double seconds;
00062 };
00063 
00064 struct EDFDecodedConfig cfg;
00065 static struct OutputBuffer ob;
00066 struct InputBuffer ib;
00067 char lineBuf[MAXLEN];
00068 int linePos = 0;
00069 int blockCounter = 0;
00070 
00071 unsigned short **sampleBuffers; // [MAXCHANNELS][MAXSAMPLES]
00072 unsigned int sampleCount;
00073 
00074 struct Options opts;
00075 
00076 void resetSampleBuffers()
00077 {
00078         sampleCount = 0;
00079 }
00080 
00081 void initSampleBuffers()
00082 {
00083         int i;
00084         sampleBuffers = calloc(sizeof(unsigned short *), cfg.hdr.dataRecordChannels);
00085         for (i = 0; i < cfg.hdr.dataRecordChannels; ++i)
00086                 sampleBuffers[i] = calloc(cfg.chan[0].sampleCount, sizeof(unsigned short));
00087         resetSampleBuffers();
00088 }
00089 
00090 void writeBuffers()
00091 {
00092         int i;
00093         FILE *fp;
00094         fp = fopen(opts.filename, "a");
00095         assert(fp != NULL && "Cannot open file!");
00096         fseek(fp, 0, SEEK_END);
00097         for (i = 0; i < cfg.hdr.dataRecordChannels; ++i)
00098                 fwrite(sampleBuffers[i], sizeof(unsigned short), sampleCount, fp);
00099         fclose(fp);
00100         rprintf("Wrote block %d\n", blockCounter);
00101         blockCounter += 1;
00102         resetSampleBuffers();
00103 }
00104 
00105 void handleSamples(int packetCounter, int channels, int *samples)
00106 {
00107         static int lastPacketCounter = 0;
00108         int i;
00109         if (lastPacketCounter + 1 != packetCounter && packetCounter != 0 && lastPacketCounter != 0) {
00110                 rprintf("May have missed packet: got packetCounters %d and %d\n", lastPacketCounter, packetCounter);
00111         }
00112         lastPacketCounter = packetCounter;
00113         for (i = 0; i < channels; ++i)
00114                 sampleBuffers[i][sampleCount] = samples[i];
00115         sampleCount += 1;
00116         if (sampleCount == cfg.chan[0].sampleCount) {
00117                 writeBuffers();
00118         }
00119 }
00120 
00121 int isANumber(const char *str) {
00122         int i;
00123         for (i = 0; str[i]; ++i)
00124                 if (!isdigit(str[i]))
00125                         return 0;
00126         return 1;
00127 }
00128 
00129 void serverDied(void)
00130 {
00131         rprintf("Server died!\n");
00132         exit(1);
00133 }
00134 
00135 int main(int argc, char **argv)
00136 {
00137         char EDFPacket[MAXHEADERLEN];
00138         char cmdbuf[80];
00139         int EDFLen = MAXHEADERLEN;
00140         FILE *fp;
00141         fd_set toread;
00142         int i;
00143         double t0;
00144         sock_t sock_fd;
00145         int retval;
00146         strcpy(opts.hostname, DEFAULTHOST);
00147         opts.port = DEFAULTPORT;
00148         for (i = 1; i < argc; ++i) {
00149                 char *opt = argv[i];
00150                 if (opt[0] == '-') {
00151                         switch (opt[1]) {
00152                                 case 'h':
00153                                         printf("%s", helpText);
00154                                         exit(0);
00155                                         break;
00156                                 case 's':
00157                                         opts.seconds = atof(argv[i+1]);
00158                                         opts.isLimittedTime = 1;
00159                                         i += 1;
00160                                         break;
00161                                 case 'e':
00162                                         opts.eegNum = atoi(argv[i+1]);
00163                                         i += 1;
00164                                         break;
00165                                 case 'n':
00166                                         strcpy(opts.hostname, argv[i+1]);
00167                                         i += 1;
00168                                         break;
00169                                 case 'p':
00170                                         opts.port = atoi(argv[i+1]);
00171                                         i += 1;
00172                                         break;
00173                                 }
00174                         }
00175                 else {
00176                         if (opts.isFilenameSet) {
00177                                 fprintf(stderr, "Error: only one edf file allowed: %s and %s\n",
00178                                                 opts.filename, argv[i]);
00179                                 exit(1);
00180                         }
00181                         strcpy(opts.filename, argv[i]);
00182                         opts.isFilenameSet = 1;
00183                 }
00184         }
00185         rinitNetworking();
00186         if (!opts.isFilenameSet) {
00187                 fprintf(stderr, "Must supply the filename of the EDF to write.\n");
00188                 exit(1);
00189         }
00190         fp = fopen(opts.filename, "wb");
00191         assert(fp != NULL && "Cannot open file!");
00192 
00193         sock_fd = rsocket();
00194         if (sock_fd < 0) {
00195                 perror("socket");
00196                 rexit(1);
00197         }
00198 
00199         retval = rconnectName(sock_fd, opts.hostname, opts.port);
00200         if (retval != 0) {
00201                 rprintf("connect error\n");
00202                 rexit(1);
00203         }
00204 
00205         rprintf("Socket connected.\n");
00206         fflush(stdout);
00207 
00208         writeString(sock_fd, "display\n", &ob);
00209         getOK(sock_fd, &ib);
00210         rprintf("Finished display, doing getheader.\n");
00211         sprintf(cmdbuf, "getheader %d\n", opts.eegNum);
00212         writeString(sock_fd, cmdbuf, &ob);
00213         getOK(sock_fd, &ib);
00214         if (isEOF(sock_fd, &ib))
00215                 serverDied();
00216         EDFLen = readline(sock_fd, EDFPacket, sizeof(EDFPacket), &ib);
00217         rprintf("Got EDF Header <%s>, of size %d\n", EDFPacket, EDFLen);
00218         fwrite(EDFPacket, 1, EDFLen, fp);
00219         fclose(fp);
00220         readEDFString(&cfg, EDFPacket, EDFLen);
00221         initSampleBuffers();
00222         sprintf(cmdbuf, "watch %d\n", opts.eegNum);
00223         writeString(sock_fd, cmdbuf, &ob);
00224         getOK(sock_fd, &ib);
00225         t0 = pctimer();
00226   for (;;) {
00227     char *cur;
00228     int vals[MAXCHANNELS + 5];
00229     int curParam = 0;
00230     int devNum, packetCounter=0, channels=0, *samples;
00231     FD_ZERO(&toread);
00232     FD_SET(sock_fd, &toread);
00233     rselect(sock_fd+1, &toread, NULL, NULL);
00234     linePos = readline(sock_fd, lineBuf, sizeof(EDFPacket), &ib);
00235     if (isEOF(sock_fd, &ib))
00236       break;
00237     if (opts.isLimittedTime && pctimer() > t0 + opts.seconds)
00238       break;
00239     if (linePos < MINLINELENGTH) {
00240       rsleep(20);
00241       continue;
00242     }
00243     if (lineBuf[0] != '!')
00244       continue;
00245     for (cur = strtok(lineBuf, DELIMS); cur ; cur = strtok(NULL, DELIMS)) {
00246       if (isANumber(cur))
00247         vals[curParam++] = atoi(cur);
00248     }
00249     // <devicenum> <packetcounter> <channels> data0 data1 data2 ...
00250     if (curParam < 3)
00251       continue;
00252     devNum = vals[0];
00253     packetCounter = vals[1];
00254     channels = vals[2];
00255     samples = vals + 3;
00256     handleSamples(packetCounter, channels, samples);
00257 //                              for (i = 0; i < channels; ++i) {
00258 //                                      rprintf(" %d", samples[i]);
00259 //                              }
00260   }
00261         writeString(sock_fd, "close\n", &ob);
00262         getOK(sock_fd, &ib);
00263         return 0;
00264 }

Generated on Tue Feb 8 00:05:17 2005 for Neuroserver by doxygen 1.3.3