]> git.rkrishnan.org Git - dttsp.git/blob - jDttSP/win/winmain.c~
Upgraded windows alternatives
[dttsp.git] / jDttSP / win / winmain.c~
1 /* main.c
2
3 This file is part of a program that implements a Software-Defined Radio.
4
5 Copyright (C) 2004-5 by Frank Brickle, AB2KT and Bob McGwier, N4HY
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21 The authors can be reached by email at
22
23 ab2kt@arrl.net
24 or
25 rwmcgwier@comcast.net
26
27 or by paper mail at
28
29 The DTTS Microwave Society
30 6 Kathleen Place
31 Bridgewater, NJ 08807
32 */  
33   
34 #include <common.h>
35   
36 /////////////////////////////////////////////////////////////////////////
37
38 // Windows SHTUFF
39
40 PRIVATE CRITICAL_SECTION        csobj;
41 PRIVATE CRITICAL_SECTION cs_updobj;
42 PRIVATE LPCRITICAL_SECTION  cs;
43 PRIVATE LPCRITICAL_SECTION cs_upd;
44 PRIVATE BOOLEAN IC=FALSE;
45
46 // elementary defaults
47 struct _loc  loc;  
48
49 /////////////////////////////////////////////////////////////////////////
50 // most of what little we know here about the inner loop,
51 // functionally speaking
52
53 extern void reset_meters(void);
54 extern void reset_spectrum(void);
55 extern void reset_counters(void);
56 extern void process_samples(float *, float *, float *, float *, int);
57 extern void setup_workspace(void);
58 extern void destroy_workspace(void);
59
60 //========================================================================
61
62 PRIVATE void
63 spectrum_thread(void) {
64   DWORD NumBytesWritten;
65   while (top.running) {
66     sem_wait(&top.sync.pws.sem);
67     compute_spectrum(&uni.spec);
68         WriteFile(top.meas.spec.fd,(LPVOID)&uni.spec.label,
69                 sizeof(int),&NumBytesWritten,NULL);
70         WriteFile(top.meas.spec.fd,(LPVOID)uni.spec.output,
71                 sizeof(float)*uni.spec.size,&NumBytesWritten,NULL);
72   }
73   pthread_exit(0);
74 }
75
76 /*PRIVATE void
77 scope_thread(void) {
78   DWORD NumBytesWritten;
79   while (top.running) {
80     sem_wait(&top.sync.scope.sem);
81     compute_spectrum(&uni.spec);
82         WriteFile(top.meas.scope.fd,(LPVOID)&uni.spec.label,
83                 sizeof(int),&NumBytesWritten,NULL);
84         WriteFile(top.meas.scope.fd,(LPVOID)uni.spec.accum,
85                 sizeof(float)*uni.spec.size,&NumBytesWritten,NULL);
86   }
87   pthread_exit(0);
88 } */
89
90 PRIVATE void
91 meter_thread(void) {
92   DWORD NumBytesWritten;
93   while (top.running) {
94     sem_wait(&top.sync.mtr.sem);
95         WriteFile(top.meas.mtr.fd,(LPVOID)&uni.meter.label, sizeof(int),&NumBytesWritten,NULL);
96         WriteFile(top.meas.mtr.fd,(LPVOID)&uni.meter.snap.rx,sizeof(REAL)*MAXRX * RXMETERPTS,&NumBytesWritten,NULL);
97         WriteFile(top.meas.mtr.fd,(LPVOID)&uni.meter.snap.tx,sizeof(REAL)*TXMETERPTS,&NumBytesWritten,NULL);
98   }
99   pthread_exit(0);   
100 }
101
102 //========================================================================
103
104 PRIVATE void
105 monitor_thread(void) {
106   while (top.running) {
107     sem_wait(&top.sync.mon.sem);
108    /* If there is anything that needs monitoring, do it here */
109     fprintf(stderr,
110             "@@@ mon [%d]: cb = %d rbi = %d rbo = %d xr = %d\n",
111             uni.tick,
112             top.jack.blow.cb,
113             top.jack.blow.rb.i,
114             top.jack.blow.rb.o,
115             top.jack.blow.xr);
116     memset((char *) &top.jack.blow, 0, sizeof(top.jack.blow));
117   }
118   pthread_exit(0); 
119   
120 }
121
122 //========================================================================
123
124 PRIVATE void 
125 process_updates_thread(void) {
126   
127   while (top.running) {
128           DWORD NumBytesRead;
129           pthread_testcancel();
130           while (ReadFile(top.parm.fd,top.parm.buff,256,&NumBytesRead,NULL))
131           {
132                   fprintf(stderr,"Update Bytes:%lu Msg:%s\n",NumBytesRead,top.parm.buff),fflush(stderr);
133                   if (NumBytesRead != 0) do_update(top.parm.buff, top.verbose ? stderr : 0);
134           }
135   }
136   pthread_exit(0);
137 }
138
139 //========================================================================
140
141
142 PRIVATE void
143 gethold(void) {
144   EnterCriticalSection(cs);
145   if (ringb_write_space(top.jack.ring.o.l)
146       < top.hold.size.bytes) {
147     // pathology
148     ringb_reset(top.jack.ring.o.l);
149     ringb_reset(top.jack.ring.o.r);
150     top.jack.blow.rb.o++;
151   }
152   ringb_write(top.jack.ring.o.l,
153                         (char *) top.hold.buf.l,
154                         top.hold.size.bytes);
155   ringb_write(top.jack.ring.o.r,
156                         (char *) top.hold.buf.r,
157                         top.hold.size.bytes);
158   if (ringb_read_space(top.jack.ring.i.l)
159       < top.hold.size.bytes) {
160     // pathology
161     ringb_reset(top.jack.ring.i.l);
162     ringb_reset(top.jack.ring.i.r);
163     memset((char *) top.hold.buf.l, 0, top.hold.size.bytes);
164     memset((char *) top.hold.buf.r, 0, top.hold.size.bytes);
165     ringb_reset(top.jack.auxr.i.l);
166     ringb_reset(top.jack.auxr.i.r);
167     memset((char *) top.hold.aux.l, 0, top.hold.size.bytes);
168     memset((char *) top.hold.aux.r, 0, top.hold.size.bytes);
169     top.jack.blow.rb.i++;
170   } else {
171     ringb_read(top.jack.ring.i.l,
172                          (char *) top.hold.buf.l,
173                          top.hold.size.bytes);
174     ringb_read(top.jack.ring.i.r,
175                          (char *) top.hold.buf.r,
176                          top.hold.size.bytes);
177     ringb_read(top.jack.auxr.i.l,
178                          (char *) top.hold.aux.l,
179                          top.hold.size.bytes);
180     ringb_read(top.jack.auxr.i.r,
181                          (char *) top.hold.aux.r,
182                          top.hold.size.bytes);
183   }
184   LeaveCriticalSection(cs);
185 }
186
187 PRIVATE BOOLEAN
188 canhold(void) {
189   BOOLEAN answer;
190   EnterCriticalSection(cs);
191   answer = (ringb_read_space(top.jack.ring.i.l) >= top.hold.size.bytes);
192   LeaveCriticalSection(cs);
193   return answer;
194 }
195
196
197 //------------------------------------------------------------------------
198
199 PRIVATE void 
200 run_mute(void) {
201   memset((char *) top.hold.buf.l, 0, top.hold.size.bytes);
202   memset((char *) top.hold.buf.r, 0, top.hold.size.bytes);
203   memset((char *) top.hold.aux.l, 0, top.hold.size.bytes);
204   memset((char *) top.hold.aux.r, 0, top.hold.size.bytes);
205   uni.tick++;
206 }
207
208 PRIVATE void 
209 run_pass(void) { uni.tick++; }
210
211 PRIVATE void 
212 run_play(void) {
213   process_samples(top.hold.buf.l, top.hold.buf.r,
214                   top.hold.aux.l, top.hold.aux.r,
215                   top.hold.size.frames);
216
217
218 // NB do not set RUN_SWCH directly via setRunState;
219 // use setSWCH instead
220
221 PRIVATE void 
222 run_swch(void) {
223   if (top.swch.bfct.have == 0) {
224     // first time
225     // apply ramp down
226     int i, m = top.swch.fade, n = top.swch.tail;
227     for (i = 0; i < m; i++) {
228       float w = (float) 1.0 - (float) i / m;
229       top.hold.buf.l[i] *= w, top.hold.buf.r[i] *= w;
230     }
231     memset((char *) (top.hold.buf.l + m), 0, n);
232     memset((char *) (top.hold.buf.r + m), 0, n);
233     top.swch.bfct.have++;
234   } else if (top.swch.bfct.have < top.swch.bfct.want) {
235     // in medias res
236     memset((char *) top.hold.buf.l, 0, top.hold.size.bytes);
237     memset((char *) top.hold.buf.r, 0, top.hold.size.bytes);
238     top.swch.bfct.have++;
239   } else {
240     // last time
241     // apply ramp up
242     int i, m = top.swch.fade, n = top.swch.tail;
243     for (i = 0; i < m; i++) {
244       float w = (float) i / m;
245       top.hold.buf.l[i] *= w, top.hold.buf.r[i] *= w;
246     }
247     uni.mode.trx = top.swch.trx.next;
248         switch (uni.mode.trx) {
249                 int i;
250                 case TX:
251                         tx.agc.gen->over = tx.tick + 3;
252                         break;
253                 case RX:
254                         for(i=0;i<uni.multirx.nrx;i++) rx[i].agc.gen->over = rx[i].tick + 3;
255                         break;
256         }
257
258     top.state = top.swch.run.last;
259     top.swch.bfct.want = top.swch.bfct.have = 0;
260
261     ringb_reset(top.jack.ring.o.l);
262     ringb_reset(top.jack.ring.o.r);
263     ringb_clear(top.jack.ring.o.l,top.hold.size.bytes);
264     ringb_clear(top.jack.ring.o.r,top.hold.size.bytes);
265
266     reset_meters();
267     reset_spectrum();
268     reset_counters();
269   }
270
271   process_samples(top.hold.buf.l, top.hold.buf.r,
272                   top.hold.aux.l, top.hold.aux.r,
273                   top.hold.size.frames);
274
275
276 //========================================================================
277
278
279
280 DttSP_EXP void
281 audio_callback(float *input_l, float *input_r, float *output_l, float *output_r,int nframes) {
282   size_t nbytes = sizeof(float)*nframes;
283
284
285   EnterCriticalSection(cs);
286
287
288     if (ringb_read_space(top.jack.ring.o.l) >= nbytes) {
289       ringb_read(top.jack.ring.o.l, (char *) output_l, nbytes);
290       ringb_read(top.jack.ring.o.r, (char *) output_r, nbytes);
291     } else { // rb pathology
292       memset((char *) output_l, 0, nbytes);
293       memset((char *) output_r, 0, nbytes);
294       ringb_restart(top.jack.ring.o.l, nbytes);
295       ringb_restart(top.jack.ring.o.r, nbytes);
296       top.jack.blow.rb.o++;
297     }
298     
299     // input: copy from port to ring
300     if (ringb_write_space(top.jack.ring.i.l) >= nbytes) {
301       ringb_write(top.jack.ring.i.l, (char *) input_l, nbytes);
302       ringb_write(top.jack.ring.i.r, (char *) input_r, nbytes);
303       ringb_write(top.jack.auxr.i.l, (char *) input_l, nbytes);
304       ringb_write(top.jack.auxr.i.r, (char *) input_r, nbytes);
305     } else { // rb pathology
306       ringb_restart(top.jack.ring.i.l, nbytes);
307       ringb_restart(top.jack.ring.i.r, nbytes);
308       ringb_restart(top.jack.auxr.i.l, nbytes);
309       ringb_restart(top.jack.auxr.i.r, nbytes);
310       top.jack.blow.rb.i++;
311     }
312   LeaveCriticalSection(cs);
313   // if enough accumulated in ring, fire dsp
314   if (ringb_read_space(top.jack.ring.i.l) >= top.hold.size.bytes)
315     sem_post(&top.sync.buf.sem);
316
317   // check for blowups
318   if ((top.jack.blow.cb > 0) ||
319       (top.jack.blow.rb.i > 0) ||
320       (top.jack.blow.rb.o > 0))
321     sem_post(&top.sync.mon.sem);
322 }
323
324 //========================================================================
325
326 DttSP_EXP void 
327 process_samples_thread(void) {
328   while (top.running) {
329     sem_wait(&top.sync.buf.sem);
330     do {
331       gethold();
332       sem_wait(&top.sync.upd.sem);
333       switch (top.state) {
334       case RUN_MUTE: run_mute(); break;
335       case RUN_PASS: run_pass(); break;
336       case RUN_PLAY: run_play(); break;
337       case RUN_SWCH: run_swch(); break;
338       }
339       sem_post(&top.sync.upd.sem);
340     } while (canhold());
341   }
342 }
343
344
345 void 
346 closeup(void) {
347   top.running = FALSE;
348   Sleep(50);
349   safefree((char *)top.jack.ring.o.r);
350   safefree((char *)top.jack.ring.o.l);
351   safefree((char *)top.jack.ring.i.r);
352   safefree((char *)top.jack.ring.i.l);
353   safefree((char *)top.jack.auxr.i.l);
354   safefree((char *)top.jack.auxr.i.r);
355   safefree((char *)top.jack.auxr.o.l);
356   safefree((char *)top.jack.auxr.o.r);
357
358    CloseHandle(top.parm.fp); 
359    DisconnectNamedPipe(top.parm.fd); 
360    CloseHandle(top.parm.fd); 
361
362
363   if (uni.meter.flag) {
364     CloseHandle(top.meas.mtr.fp); 
365         DisconnectNamedPipe(top.meas.mtr.fd); 
366         CloseHandle(top.meas.mtr.fd); 
367   };
368   
369   if (uni.spec.flag) {
370           CloseHandle(top.meas.spec.fp); 
371           DisconnectNamedPipe(top.meas.spec.fd); 
372           CloseHandle(top.meas.spec.fd); 
373   };
374   destroy_workspace();
375 }
376
377 //........................................................................
378
379 PRIVATE void 
380 setup_switching(void) {
381   top.swch.fade = (int) (0.1 * uni.buflen + 0.5);
382   top.swch.tail = (top.hold.size.frames - top.swch.fade) * sizeof(float);
383 }
384
385 PRIVATE void 
386 setup_local_audio(void) {
387   top.hold.size.frames = uni.buflen;
388   top.hold.size.bytes = top.hold.size.frames * sizeof(float);
389   top.hold.buf.l = (float *) safealloc(top.hold.size.frames, sizeof(float),
390                                        "main hold buffer left");
391   top.hold.buf.r = (float *) safealloc(top.hold.size.frames, sizeof(float),
392                                        "main hold buffer right");
393   top.hold.aux.l = (float *) safealloc(top.hold.size.frames, sizeof(float),
394                                        "aux hold buffer left");
395   top.hold.aux.r = (float *) safealloc(top.hold.size.frames, sizeof(float),
396                                        "aux hold buffer right");
397 }
398
399 #include <lmerr.h>
400
401 PRIVATE void
402 DisplayErrorText(DWORD dwLastError)
403 {
404     HMODULE hModule = NULL; // default to system source
405     LPSTR MessageBuffer;
406     DWORD dwBufferLength;
407
408     DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
409         FORMAT_MESSAGE_IGNORE_INSERTS |
410         FORMAT_MESSAGE_FROM_SYSTEM ;
411
412     //
413     // If dwLastError is in the network range, 
414     //  load the message source.
415     //
416
417     if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {
418         hModule = LoadLibraryEx(
419             TEXT("netmsg.dll"),
420             NULL,
421             LOAD_LIBRARY_AS_DATAFILE
422             );
423
424         if(hModule != NULL)
425             dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
426     }
427
428     //
429     // Call FormatMessage() to allow for message 
430     //  text to be acquired from the system 
431     //  or from the supplied module handle.
432     //
433
434     if(dwBufferLength = FormatMessageA(
435         dwFormatFlags,
436         hModule, // module to get message from (NULL == system)
437         dwLastError,
438         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
439         (LPSTR) &MessageBuffer,
440         0,
441         NULL
442         ))
443     {
444         DWORD dwBytesWritten;
445
446         //
447         // Output message string on stderr.
448         //
449         WriteFile(
450             GetStdHandle(STD_ERROR_HANDLE),
451             MessageBuffer,
452             dwBufferLength,
453             &dwBytesWritten,
454             NULL
455             );
456
457         //
458         // Free the buffer allocated by the system.
459         //
460         LocalFree(MessageBuffer);
461     }
462
463     //
464     // If we loaded a message source, unload it.
465     //
466     if(hModule != NULL)
467         FreeLibrary(hModule);
468 }
469
470
471
472 PRIVATE sem_t setup_update_sem;
473
474 PRIVATE void setup_update_server()
475 {
476
477   if (INVALID_HANDLE_VALUE == (top.parm.fd = CreateNamedPipe(top.parm.path,
478                         PIPE_ACCESS_INBOUND,
479                         PIPE_WAIT|PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE,
480                         PIPE_UNLIMITED_INSTANCES,
481                         512,
482                         512,
483                         INFINITE,
484                         NULL)))
485   {
486           fprintf(stderr,"Update server pipe setup failed:\n"),fflush(stderr);
487           DisplayErrorText(GetLastError());
488  }
489 //  fprintf(stderr,"Update NamedPipe made\n"),fflush(stderr);
490   sem_post(&setup_update_sem);
491   if (ConnectNamedPipe(top.parm.fd,NULL))
492   {
493 //      fprintf(stderr,"Connected the server to the Update pipe\n"),fflush(stderr);
494   } else {
495           fprintf(stderr,"Connected the server to the Update pipe failed\n"),fflush(stderr);
496           DisplayErrorText(GetLastError());
497   }
498         pthread_exit(0);
499 }
500
501
502 PRIVATE void setup_update_client()
503 {
504 //      fprintf(stderr,"Looking for the Update server\n"),fflush(stderr);
505         WaitNamedPipe(top.parm.path,INFINITE);
506 //      fprintf(stderr,"Found the Update server\n"),fflush(stderr);
507         if (INVALID_HANDLE_VALUE == (top.parm.fp = CreateFile(top.parm.path,
508         GENERIC_WRITE, 0, NULL,
509     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
510         {
511                 fprintf(stderr,"The Update Client Open Failed\n"),fflush(stderr);
512                 DisplayErrorText(GetLastError());
513         }
514         sem_post(&setup_update_sem);
515 /*      {
516                 DWORD numwritten;
517                 WriteFile(top.parm.fp,"test",5,&numwritten,NULL);
518                 fprintf(stderr,"Number written to server: %lu\n",numwritten),fflush(stderr);
519         }*/
520         pthread_exit(0);
521 }
522
523 PRIVATE void setup_meter_server()
524 {
525   top.meas.mtr.fd = CreateNamedPipe(top.meas.mtr.path,
526                         PIPE_ACCESS_OUTBOUND,
527                         PIPE_WAIT|PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE,
528                         PIPE_UNLIMITED_INSTANCES,
529                         512,
530                         512,
531                         INFINITE,
532                         NULL);
533 //  fprintf(stderr,"meter handle = %08X\n",(DWORD)top.meas.mtr.fd),fflush(stderr);
534   if (top.meas.mtr.fd == INVALID_HANDLE_VALUE)
535   { 
536           fprintf(stderr,"Meter server pipe setup failed:\n"),fflush(stderr);
537           DisplayErrorText(GetLastError());
538   } else {
539 //        fprintf(stderr,"Meter Pipe Connect succeeded\n"),fflush(stderr);
540           sem_post(&setup_update_sem);
541           if (ConnectNamedPipe(top.meas.mtr.fd,NULL)) {
542 //          fprintf(stderr,"Connected the Meter Pooch\n"),fflush(stderr);
543           } else {
544                   fprintf(stderr,"Meter Pipe Connect failed\n"),fflush(stderr);
545                   DisplayErrorText(GetLastError());
546           }
547   }
548   pthread_exit(0);
549 }
550
551 PRIVATE void setup_meter_client()
552 {
553 //      fprintf(stderr,"Looking for the meter server\n"),fflush(stderr);
554         if (WaitNamedPipe(top.meas.mtr.path,INFINITE)) {
555 //        fprintf(stderr,"Found the Meter server\n"),fflush(stderr);
556                 if (INVALID_HANDLE_VALUE == (top.meas.mtr.fp = CreateFile(top.meas.mtr.path,
557                         GENERIC_READ, 0, NULL,
558                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
559                 {
560                         fprintf(stderr,"The Meter Client Open Failed\n"),fflush(stderr);
561                         DisplayErrorText(GetLastError());
562                 } else {
563 //                      fprintf(stderr,"The Meter Client Open Succeeded\n"),fflush(stderr);
564                 }
565         } else {
566                 fprintf(stderr,"Wait for meter pipe failed: Error message %d\n",GetLastError()),fflush(stderr);
567         }
568         sem_post(&setup_update_sem);
569         pthread_exit(0);
570 }
571
572 PRIVATE void setup_spec_server()
573 {
574
575   if (INVALID_HANDLE_VALUE == (top.meas.spec.fd = CreateNamedPipe(top.meas.spec.path,
576                         PIPE_ACCESS_OUTBOUND,
577                         PIPE_WAIT|PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE,
578                         PIPE_UNLIMITED_INSTANCES,
579                         32768,
580                         32768,
581                         INFINITE,
582                         NULL)))
583   {
584           fprintf(stderr,"Spectrum pipe create failed\n"),fflush(stderr);
585           DisplayErrorText(GetLastError());
586   } else {
587 //        fprintf(stderr,"Spectrum Pipe %s Create succeeded\n",top.meas.spec.path),fflush(stderr);
588           sem_post(&setup_update_sem);
589           if (ConnectNamedPipe(top.meas.spec.fd,NULL))
590           {
591 //          fprintf(stderr,"Connected to the Spectrum Pipe\n"),fflush(stderr);
592           } else {
593                   fprintf(stderr,"Spectrum pipe connect failed\n"),fflush(stderr);
594                   DisplayErrorText(GetLastError());
595           }
596   }
597   pthread_exit(0);
598 }
599
600 PRIVATE void setup_spec_client()
601 {
602 //      fprintf(stderr,"Looking for the spectrum server\n"),fflush(stderr);
603         if (WaitNamedPipe(top.meas.spec.path,INFINITE)) {
604 //              fprintf(stderr,"Found the server\n"),fflush(stderr);
605                 if (INVALID_HANDLE_VALUE == (top.meas.spec.fp = CreateFile(top.meas.spec.path,
606                         GENERIC_READ, 0, NULL,
607                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
608                 {
609                         fprintf(stderr,"The Spectrum Client Open Failed\n"),fflush(stderr);
610                         DisplayErrorText(GetLastError());
611                 } else {
612 //                      fprintf(stderr,"The Spectrum Client Open Succeeded\n");
613 //                      fprintf(stderr,"Spec Read handle = %08X\n",(DWORD)top.meas.spec.fp),fflush(stderr);
614                 }
615         } else {
616                 fprintf(stderr,"Wait for spec pipe failed\n"),fflush(stderr);
617                 DisplayErrorText(GetLastError());
618         }
619         sem_post(&setup_update_sem);
620         pthread_exit(0);
621 }
622 PRIVATE pthread_t id1,id2,id3,id4,id5,id6;
623 PRIVATE void 
624 setup_updates(void) {
625
626   char mesg[16384]="TEST TEST METER\n";
627 //  DWORD NumBytes;
628   top.parm.path = loc.path.parm;
629   sem_init(&setup_update_sem, 0, 0);
630   
631
632   if (uni.meter.flag) {
633     top.meas.mtr.path = loc.path.meter;
634   }
635   if (uni.spec.flag) {
636     top.meas.spec.path = loc.path.spec;
637   }
638
639    
640           // Do this STUPID stuff to make use of the Named Pipe Mechanism in Windows
641           // For the update server
642
643         
644   pthread_create(&id1, NULL, (void *) setup_update_server, NULL);
645   sem_wait(&setup_update_sem);
646   pthread_create(&id2, NULL, (void *) setup_update_client, NULL);
647   sem_wait(&setup_update_sem);
648   if (uni.meter.flag) {
649           pthread_create(&id3, NULL, (void *) setup_meter_server, NULL);
650           sem_wait(&setup_update_sem);
651           pthread_create(&id4, NULL, (void *) setup_meter_client, NULL);
652           sem_wait(&setup_update_sem);
653 /*        if (WriteFile(top.meas.mtr.fd,mesg,strlen(mesg)+1,&NumBytes,NULL))
654           {
655                   fprintf(stderr,"Meter Pipe write succeeded and wrote %lu bytes\n",NumBytes),fflush(stderr);
656           } else {
657                   fprintf(stderr,"Meter Pipe write failed\n"),fflush(stderr);
658                   DisplayErrorText(GetLastError());
659           }
660           if (ReadFile(top.meas.mtr.fp,mesg,256,&NumBytes,NULL))
661           {
662                   fprintf(stderr,"Meter Pipe read succeeded and %lu bytes read\n",NumBytes),fflush(stderr);
663                   fprintf(stderr,"Meter message %s",mesg),fflush(stderr);
664           } else {
665                   fprintf(stderr,"Meter Pipe read failed\n"),fflush(stderr);
666                   DisplayErrorText(GetLastError());
667           }*/
668           
669   }
670  
671   if (uni.spec.flag) {
672           memset(mesg,0,16384);
673           pthread_create(&id5, NULL, (void *) setup_spec_server, NULL);
674           sem_wait(&setup_update_sem);
675           pthread_create(&id6, NULL, (void *) setup_spec_client, NULL);
676           sem_wait(&setup_update_sem);
677           Sleep(0);
678 /*        if (WriteFile(top.meas.spec.fd,mesg,16384,&NumBytes,NULL))
679           {
680                   fprintf(stderr,"Spec Pipe write succeeded and wrote %lu bytes\n",NumBytes),fflush(stderr);
681           } else {
682                   fprintf(stderr,"Spec Pipe write failed\n"),fflush(stderr);
683                   DisplayErrorText(GetLastError());
684           }
685           fprintf(stderr,"Spec Read handle(2) = %08X\n",(DWORD)top.meas.spec.fp),fflush(stderr);
686           if (ReadFile(top.meas.spec.fp,mesg,16384,&NumBytes,NULL))
687           {
688                   fprintf(stderr,"Spec Pipe read succeeded and %lu bytes read\n",NumBytes),fflush(stderr);
689           } else {
690                   fprintf(stderr,"Spec Pipe read failed\n"),fflush(stderr);
691                   DisplayErrorText(GetLastError());
692           } */
693   }
694   sem_destroy(&setup_update_sem);
695 }
696 PRIVATE void 
697 setup_system_audio(void) {
698         size_t ringsize;
699         void *usemem;
700         sprintf(top.jack.name, "sdr-%d", top.pid);
701         top.jack.size = uni.buflen;
702         ringsize = top.hold.size.bytes * loc.mult.ring+sizeof(ringb_t);
703         usemem = safealloc(ringsize,1,"Ring Input Left");
704         top.jack.ring.i.l = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
705
706         usemem = safealloc(ringsize,1,"Ring Input Right");
707         top.jack.ring.i.r = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
708
709         usemem = safealloc(ringsize,1,"Ring Output Left");
710         top.jack.ring.o.l = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
711
712         usemem = safealloc(ringsize,1,"Ring Output Right");
713         top.jack.ring.o.r = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
714
715         usemem = safealloc(ringsize,1,"Ring Input Left Auxiliary");
716         top.jack.auxr.i.l = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
717
718         usemem = safealloc(ringsize,1,"Ring Input Right Auxiliary");
719         top.jack.auxr.i.r = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
720
721         usemem = safealloc(ringsize,1,"Ring Output Left Auxiliary");
722         top.jack.auxr.o.l = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
723
724         usemem = safealloc(ringsize,1,"Ring Output Right Auxiliary");
725         top.jack.auxr.o.r = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
726
727         ringb_clear(top.jack.ring.o.l, top.jack.size * sizeof(float));
728         ringb_clear(top.jack.ring.o.r, top.jack.size * sizeof(float));
729         ringb_clear(top.jack.auxr.o.l, top.jack.size * sizeof(float));
730         ringb_clear(top.jack.auxr.o.r, top.jack.size * sizeof(float));
731 }
732
733 PRIVATE void 
734 setup_threading(void) {
735   sem_init(&top.sync.upd.sem, 0, 0);
736   pthread_create(&top.thrd.upd.id, NULL, (void *) process_updates_thread, NULL);
737   sem_init(&top.sync.buf.sem, 0, 0);
738   pthread_create(&top.thrd.trx.id, NULL, (void *) process_samples_thread, NULL);
739   sem_init(&top.sync.mon.sem, 0, 0);
740   pthread_create(&top.thrd.mon.id, NULL, (void *) monitor_thread, NULL);
741   if (uni.meter.flag) {
742     sem_init(&top.sync.mtr.sem, 0, 0);
743     pthread_create(&top.thrd.mtr.id, NULL, (void *) meter_thread, NULL);
744   }
745   if (uni.spec.flag) {
746     sem_init(&top.sync.pws.sem, 0, 0);
747     pthread_create(&top.thrd.pws.id, NULL, (void *) spectrum_thread, NULL);
748   }
749   cs = &csobj;
750   InitializeCriticalSection(cs);
751
752
753 //========================================================================
754 // hard defaults, then environment
755
756 PRIVATE void
757 setup_defaults(void) {
758   loc.name[0] = 0; // no default name for jack client
759   strcpy(loc.path.rcfile, RCBASE);
760   strcpy(loc.path.parm, PARMPATH);
761   strcpy(loc.path.meter, METERPATH);
762   strcpy(loc.path.spec, SPECPATH);
763   strcpy(loc.path.wisdom, WISDOMPATH);
764   loc.def.rate = DEFRATE;
765   loc.def.size = DEFSIZE;
766   loc.def.nrx = MAXRX;
767   loc.def.mode = DEFMODE;
768   loc.def.spec = DEFSPEC;
769   loc.mult.ring = RINGMULT;
770 }
771
772 //========================================================================
773 void 
774 setup() {
775
776
777   top.pid = GetCurrentThreadId();
778   top.uid = 0L;
779   top.start_tv = now_tv();
780   top.running = TRUE;
781   top.verbose = FALSE;
782   top.state = RUN_PLAY;
783
784   setup_defaults();
785   top.verbose = FALSE;
786   uni.meter.flag = TRUE;
787   uni.spec.flag = TRUE;
788
789   setup_workspace();
790   setup_updates();
791
792   setup_local_audio();
793   setup_system_audio();
794
795   setup_threading();
796   setup_switching();
797     uni.spec.flag = TRUE;
798         uni.spec.type  = SPEC_POST_FILT;
799         uni.spec.scale = SPEC_PWR;
800         uni.spec.rxk = 0;
801
802 }
803