00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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;
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
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
00258
00259
00260 }
00261 writeString(sock_fd, "close\n", &ob);
00262 getOK(sock_fd, &ib);
00263 return 0;
00264 }