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