]> git.rkrishnan.org Git - dttsp.git/blobdiff - jDttSP/win/winmain.c~
Upgraded windows alternatives
[dttsp.git] / jDttSP / win / winmain.c~
diff --git a/jDttSP/win/winmain.c~ b/jDttSP/win/winmain.c~
new file mode 100644 (file)
index 0000000..9832178
--- /dev/null
@@ -0,0 +1,803 @@
+/* main.c
+
+This file is part of a program that implements a Software-Defined Radio.
+
+Copyright (C) 2004-5 by Frank Brickle, AB2KT and Bob McGwier, N4HY
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+The authors can be reached by email at
+
+ab2kt@arrl.net
+or
+rwmcgwier@comcast.net
+
+or by paper mail at
+
+The DTTS Microwave Society
+6 Kathleen Place
+Bridgewater, NJ 08807
+*/  
+  
+#include <common.h>
+  
+/////////////////////////////////////////////////////////////////////////
+
+// Windows SHTUFF
+
+PRIVATE CRITICAL_SECTION       csobj;
+PRIVATE CRITICAL_SECTION cs_updobj;
+PRIVATE LPCRITICAL_SECTION  cs;
+PRIVATE LPCRITICAL_SECTION cs_upd;
+PRIVATE BOOLEAN IC=FALSE;
+
+// elementary defaults
+struct _loc  loc;  
+
+/////////////////////////////////////////////////////////////////////////
+// most of what little we know here about the inner loop,
+// functionally speaking
+
+extern void reset_meters(void);
+extern void reset_spectrum(void);
+extern void reset_counters(void);
+extern void process_samples(float *, float *, float *, float *, int);
+extern void setup_workspace(void);
+extern void destroy_workspace(void);
+
+//========================================================================
+
+PRIVATE void
+spectrum_thread(void) {
+  DWORD NumBytesWritten;
+  while (top.running) {
+    sem_wait(&top.sync.pws.sem);
+    compute_spectrum(&uni.spec);
+       WriteFile(top.meas.spec.fd,(LPVOID)&uni.spec.label,
+               sizeof(int),&NumBytesWritten,NULL);
+       WriteFile(top.meas.spec.fd,(LPVOID)uni.spec.output,
+               sizeof(float)*uni.spec.size,&NumBytesWritten,NULL);
+  }
+  pthread_exit(0);
+}
+
+/*PRIVATE void
+scope_thread(void) {
+  DWORD NumBytesWritten;
+  while (top.running) {
+    sem_wait(&top.sync.scope.sem);
+    compute_spectrum(&uni.spec);
+       WriteFile(top.meas.scope.fd,(LPVOID)&uni.spec.label,
+               sizeof(int),&NumBytesWritten,NULL);
+       WriteFile(top.meas.scope.fd,(LPVOID)uni.spec.accum,
+               sizeof(float)*uni.spec.size,&NumBytesWritten,NULL);
+  }
+  pthread_exit(0);
+} */
+
+PRIVATE void
+meter_thread(void) {
+  DWORD NumBytesWritten;
+  while (top.running) {
+    sem_wait(&top.sync.mtr.sem);
+       WriteFile(top.meas.mtr.fd,(LPVOID)&uni.meter.label, sizeof(int),&NumBytesWritten,NULL);
+       WriteFile(top.meas.mtr.fd,(LPVOID)&uni.meter.snap.rx,sizeof(REAL)*MAXRX * RXMETERPTS,&NumBytesWritten,NULL);
+       WriteFile(top.meas.mtr.fd,(LPVOID)&uni.meter.snap.tx,sizeof(REAL)*TXMETERPTS,&NumBytesWritten,NULL);
+  }
+  pthread_exit(0);   
+}
+
+//========================================================================
+
+PRIVATE void
+monitor_thread(void) {
+  while (top.running) {
+    sem_wait(&top.sync.mon.sem);
+   /* If there is anything that needs monitoring, do it here */
+    fprintf(stderr,
+           "@@@ mon [%d]: cb = %d rbi = %d rbo = %d xr = %d\n",
+           uni.tick,
+           top.jack.blow.cb,
+           top.jack.blow.rb.i,
+           top.jack.blow.rb.o,
+           top.jack.blow.xr);
+    memset((char *) &top.jack.blow, 0, sizeof(top.jack.blow));
+  }
+  pthread_exit(0); 
+  
+}
+
+//========================================================================
+
+PRIVATE void 
+process_updates_thread(void) {
+  
+  while (top.running) {
+         DWORD NumBytesRead;
+         pthread_testcancel();
+         while (ReadFile(top.parm.fd,top.parm.buff,256,&NumBytesRead,NULL))
+         {
+                 fprintf(stderr,"Update Bytes:%lu Msg:%s\n",NumBytesRead,top.parm.buff),fflush(stderr);
+                 if (NumBytesRead != 0) do_update(top.parm.buff, top.verbose ? stderr : 0);
+         }
+  }
+  pthread_exit(0);
+}
+
+//========================================================================
+
+
+PRIVATE void
+gethold(void) {
+  EnterCriticalSection(cs);
+  if (ringb_write_space(top.jack.ring.o.l)
+      < top.hold.size.bytes) {
+    // pathology
+    ringb_reset(top.jack.ring.o.l);
+    ringb_reset(top.jack.ring.o.r);
+    top.jack.blow.rb.o++;
+  }
+  ringb_write(top.jack.ring.o.l,
+                       (char *) top.hold.buf.l,
+                       top.hold.size.bytes);
+  ringb_write(top.jack.ring.o.r,
+                       (char *) top.hold.buf.r,
+                       top.hold.size.bytes);
+  if (ringb_read_space(top.jack.ring.i.l)
+      < top.hold.size.bytes) {
+    // pathology
+    ringb_reset(top.jack.ring.i.l);
+    ringb_reset(top.jack.ring.i.r);
+    memset((char *) top.hold.buf.l, 0, top.hold.size.bytes);
+    memset((char *) top.hold.buf.r, 0, top.hold.size.bytes);
+    ringb_reset(top.jack.auxr.i.l);
+    ringb_reset(top.jack.auxr.i.r);
+    memset((char *) top.hold.aux.l, 0, top.hold.size.bytes);
+    memset((char *) top.hold.aux.r, 0, top.hold.size.bytes);
+    top.jack.blow.rb.i++;
+  } else {
+    ringb_read(top.jack.ring.i.l,
+                        (char *) top.hold.buf.l,
+                        top.hold.size.bytes);
+    ringb_read(top.jack.ring.i.r,
+                        (char *) top.hold.buf.r,
+                        top.hold.size.bytes);
+    ringb_read(top.jack.auxr.i.l,
+                        (char *) top.hold.aux.l,
+                        top.hold.size.bytes);
+    ringb_read(top.jack.auxr.i.r,
+                        (char *) top.hold.aux.r,
+                        top.hold.size.bytes);
+  }
+  LeaveCriticalSection(cs);
+}
+
+PRIVATE BOOLEAN
+canhold(void) {
+  BOOLEAN answer;
+  EnterCriticalSection(cs);
+  answer = (ringb_read_space(top.jack.ring.i.l) >= top.hold.size.bytes);
+  LeaveCriticalSection(cs);
+  return answer;
+}
+
+
+//------------------------------------------------------------------------
+
+PRIVATE void 
+run_mute(void) {
+  memset((char *) top.hold.buf.l, 0, top.hold.size.bytes);
+  memset((char *) top.hold.buf.r, 0, top.hold.size.bytes);
+  memset((char *) top.hold.aux.l, 0, top.hold.size.bytes);
+  memset((char *) top.hold.aux.r, 0, top.hold.size.bytes);
+  uni.tick++;
+}
+
+PRIVATE void 
+run_pass(void) { uni.tick++; }
+
+PRIVATE void 
+run_play(void) {
+  process_samples(top.hold.buf.l, top.hold.buf.r,
+                 top.hold.aux.l, top.hold.aux.r,
+                 top.hold.size.frames);
+} 
+
+// NB do not set RUN_SWCH directly via setRunState;
+// use setSWCH instead
+
+PRIVATE void 
+run_swch(void) {
+  if (top.swch.bfct.have == 0) {
+    // first time
+    // apply ramp down
+    int i, m = top.swch.fade, n = top.swch.tail;
+    for (i = 0; i < m; i++) {
+      float w = (float) 1.0 - (float) i / m;
+      top.hold.buf.l[i] *= w, top.hold.buf.r[i] *= w;
+    }
+    memset((char *) (top.hold.buf.l + m), 0, n);
+    memset((char *) (top.hold.buf.r + m), 0, n);
+    top.swch.bfct.have++;
+  } else if (top.swch.bfct.have < top.swch.bfct.want) {
+    // in medias res
+    memset((char *) top.hold.buf.l, 0, top.hold.size.bytes);
+    memset((char *) top.hold.buf.r, 0, top.hold.size.bytes);
+    top.swch.bfct.have++;
+  } else {
+    // last time
+    // apply ramp up
+    int i, m = top.swch.fade, n = top.swch.tail;
+    for (i = 0; i < m; i++) {
+      float w = (float) i / m;
+      top.hold.buf.l[i] *= w, top.hold.buf.r[i] *= w;
+    }
+    uni.mode.trx = top.swch.trx.next;
+       switch (uni.mode.trx) {
+               int i;
+               case TX:
+                       tx.agc.gen->over = tx.tick + 3;
+                       break;
+               case RX:
+                       for(i=0;i<uni.multirx.nrx;i++) rx[i].agc.gen->over = rx[i].tick + 3;
+                       break;
+       }
+
+    top.state = top.swch.run.last;
+    top.swch.bfct.want = top.swch.bfct.have = 0;
+
+    ringb_reset(top.jack.ring.o.l);
+    ringb_reset(top.jack.ring.o.r);
+    ringb_clear(top.jack.ring.o.l,top.hold.size.bytes);
+    ringb_clear(top.jack.ring.o.r,top.hold.size.bytes);
+
+    reset_meters();
+    reset_spectrum();
+    reset_counters();
+  }
+
+  process_samples(top.hold.buf.l, top.hold.buf.r,
+                 top.hold.aux.l, top.hold.aux.r,
+                 top.hold.size.frames);
+} 
+
+//========================================================================
+
+
+
+DttSP_EXP void
+audio_callback(float *input_l, float *input_r, float *output_l, float *output_r,int nframes) {
+  size_t nbytes = sizeof(float)*nframes;
+
+
+  EnterCriticalSection(cs);
+
+
+    if (ringb_read_space(top.jack.ring.o.l) >= nbytes) {
+      ringb_read(top.jack.ring.o.l, (char *) output_l, nbytes);
+      ringb_read(top.jack.ring.o.r, (char *) output_r, nbytes);
+    } else { // rb pathology
+      memset((char *) output_l, 0, nbytes);
+      memset((char *) output_r, 0, nbytes);
+      ringb_restart(top.jack.ring.o.l, nbytes);
+      ringb_restart(top.jack.ring.o.r, nbytes);
+      top.jack.blow.rb.o++;
+    }
+    
+    // input: copy from port to ring
+    if (ringb_write_space(top.jack.ring.i.l) >= nbytes) {
+      ringb_write(top.jack.ring.i.l, (char *) input_l, nbytes);
+      ringb_write(top.jack.ring.i.r, (char *) input_r, nbytes);
+      ringb_write(top.jack.auxr.i.l, (char *) input_l, nbytes);
+      ringb_write(top.jack.auxr.i.r, (char *) input_r, nbytes);
+    } else { // rb pathology
+      ringb_restart(top.jack.ring.i.l, nbytes);
+      ringb_restart(top.jack.ring.i.r, nbytes);
+      ringb_restart(top.jack.auxr.i.l, nbytes);
+      ringb_restart(top.jack.auxr.i.r, nbytes);
+      top.jack.blow.rb.i++;
+    }
+  LeaveCriticalSection(cs);
+  // if enough accumulated in ring, fire dsp
+  if (ringb_read_space(top.jack.ring.i.l) >= top.hold.size.bytes)
+    sem_post(&top.sync.buf.sem);
+
+  // check for blowups
+  if ((top.jack.blow.cb > 0) ||
+      (top.jack.blow.rb.i > 0) ||
+      (top.jack.blow.rb.o > 0))
+    sem_post(&top.sync.mon.sem);
+}
+
+//========================================================================
+
+DttSP_EXP void 
+process_samples_thread(void) {
+  while (top.running) {
+    sem_wait(&top.sync.buf.sem);
+    do {
+      gethold();
+      sem_wait(&top.sync.upd.sem);
+      switch (top.state) {
+      case RUN_MUTE: run_mute(); break;
+      case RUN_PASS: run_pass(); break;
+      case RUN_PLAY: run_play(); break;
+      case RUN_SWCH: run_swch(); break;
+      }
+      sem_post(&top.sync.upd.sem);
+    } while (canhold());
+  }
+}
+
+
+void 
+closeup(void) {
+  top.running = FALSE;
+  Sleep(50);
+  safefree((char *)top.jack.ring.o.r);
+  safefree((char *)top.jack.ring.o.l);
+  safefree((char *)top.jack.ring.i.r);
+  safefree((char *)top.jack.ring.i.l);
+  safefree((char *)top.jack.auxr.i.l);
+  safefree((char *)top.jack.auxr.i.r);
+  safefree((char *)top.jack.auxr.o.l);
+  safefree((char *)top.jack.auxr.o.r);
+
+   CloseHandle(top.parm.fp); 
+   DisconnectNamedPipe(top.parm.fd); 
+   CloseHandle(top.parm.fd); 
+
+
+  if (uni.meter.flag) {
+    CloseHandle(top.meas.mtr.fp); 
+       DisconnectNamedPipe(top.meas.mtr.fd); 
+       CloseHandle(top.meas.mtr.fd); 
+  };
+  
+  if (uni.spec.flag) {
+         CloseHandle(top.meas.spec.fp); 
+         DisconnectNamedPipe(top.meas.spec.fd); 
+         CloseHandle(top.meas.spec.fd); 
+  };
+  destroy_workspace();
+}
+
+//........................................................................
+
+PRIVATE void 
+setup_switching(void) {
+  top.swch.fade = (int) (0.1 * uni.buflen + 0.5);
+  top.swch.tail = (top.hold.size.frames - top.swch.fade) * sizeof(float);
+}
+
+PRIVATE void 
+setup_local_audio(void) {
+  top.hold.size.frames = uni.buflen;
+  top.hold.size.bytes = top.hold.size.frames * sizeof(float);
+  top.hold.buf.l = (float *) safealloc(top.hold.size.frames, sizeof(float),
+                                      "main hold buffer left");
+  top.hold.buf.r = (float *) safealloc(top.hold.size.frames, sizeof(float),
+                                      "main hold buffer right");
+  top.hold.aux.l = (float *) safealloc(top.hold.size.frames, sizeof(float),
+                                      "aux hold buffer left");
+  top.hold.aux.r = (float *) safealloc(top.hold.size.frames, sizeof(float),
+                                      "aux hold buffer right");
+}
+
+#include <lmerr.h>
+
+PRIVATE void
+DisplayErrorText(DWORD dwLastError)
+{
+    HMODULE hModule = NULL; // default to system source
+    LPSTR MessageBuffer;
+    DWORD dwBufferLength;
+
+    DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
+        FORMAT_MESSAGE_IGNORE_INSERTS |
+        FORMAT_MESSAGE_FROM_SYSTEM ;
+
+    //
+    // If dwLastError is in the network range, 
+    //  load the message source.
+    //
+
+    if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {
+        hModule = LoadLibraryEx(
+            TEXT("netmsg.dll"),
+            NULL,
+            LOAD_LIBRARY_AS_DATAFILE
+            );
+
+        if(hModule != NULL)
+            dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
+    }
+
+    //
+    // Call FormatMessage() to allow for message 
+    //  text to be acquired from the system 
+    //  or from the supplied module handle.
+    //
+
+    if(dwBufferLength = FormatMessageA(
+        dwFormatFlags,
+        hModule, // module to get message from (NULL == system)
+        dwLastError,
+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
+        (LPSTR) &MessageBuffer,
+        0,
+        NULL
+        ))
+    {
+        DWORD dwBytesWritten;
+
+        //
+        // Output message string on stderr.
+        //
+        WriteFile(
+            GetStdHandle(STD_ERROR_HANDLE),
+            MessageBuffer,
+            dwBufferLength,
+            &dwBytesWritten,
+            NULL
+            );
+
+        //
+        // Free the buffer allocated by the system.
+        //
+        LocalFree(MessageBuffer);
+    }
+
+    //
+    // If we loaded a message source, unload it.
+    //
+    if(hModule != NULL)
+        FreeLibrary(hModule);
+}
+
+
+
+PRIVATE sem_t setup_update_sem;
+
+PRIVATE void setup_update_server()
+{
+
+  if (INVALID_HANDLE_VALUE == (top.parm.fd = CreateNamedPipe(top.parm.path,
+                       PIPE_ACCESS_INBOUND,
+                       PIPE_WAIT|PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE,
+                       PIPE_UNLIMITED_INSTANCES,
+                       512,
+                       512,
+                       INFINITE,
+                       NULL)))
+  {
+         fprintf(stderr,"Update server pipe setup failed:\n"),fflush(stderr);
+         DisplayErrorText(GetLastError());
+ }
+//  fprintf(stderr,"Update NamedPipe made\n"),fflush(stderr);
+  sem_post(&setup_update_sem);
+  if (ConnectNamedPipe(top.parm.fd,NULL))
+  {
+//     fprintf(stderr,"Connected the server to the Update pipe\n"),fflush(stderr);
+  } else {
+         fprintf(stderr,"Connected the server to the Update pipe failed\n"),fflush(stderr);
+         DisplayErrorText(GetLastError());
+  }
+       pthread_exit(0);
+}
+
+
+PRIVATE void setup_update_client()
+{
+//     fprintf(stderr,"Looking for the Update server\n"),fflush(stderr);
+       WaitNamedPipe(top.parm.path,INFINITE);
+//     fprintf(stderr,"Found the Update server\n"),fflush(stderr);
+       if (INVALID_HANDLE_VALUE == (top.parm.fp = CreateFile(top.parm.path,
+       GENERIC_WRITE, 0, NULL,
+    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
+       {
+               fprintf(stderr,"The Update Client Open Failed\n"),fflush(stderr);
+               DisplayErrorText(GetLastError());
+       }
+       sem_post(&setup_update_sem);
+/*     {
+               DWORD numwritten;
+               WriteFile(top.parm.fp,"test",5,&numwritten,NULL);
+               fprintf(stderr,"Number written to server: %lu\n",numwritten),fflush(stderr);
+       }*/
+       pthread_exit(0);
+}
+
+PRIVATE void setup_meter_server()
+{
+  top.meas.mtr.fd = CreateNamedPipe(top.meas.mtr.path,
+                       PIPE_ACCESS_OUTBOUND,
+                       PIPE_WAIT|PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE,
+                       PIPE_UNLIMITED_INSTANCES,
+                       512,
+                       512,
+                       INFINITE,
+                       NULL);
+//  fprintf(stderr,"meter handle = %08X\n",(DWORD)top.meas.mtr.fd),fflush(stderr);
+  if (top.meas.mtr.fd == INVALID_HANDLE_VALUE)
+  { 
+         fprintf(stderr,"Meter server pipe setup failed:\n"),fflush(stderr);
+         DisplayErrorText(GetLastError());
+  } else {
+//       fprintf(stderr,"Meter Pipe Connect succeeded\n"),fflush(stderr);
+         sem_post(&setup_update_sem);
+         if (ConnectNamedPipe(top.meas.mtr.fd,NULL)) {
+//          fprintf(stderr,"Connected the Meter Pooch\n"),fflush(stderr);
+         } else {
+                 fprintf(stderr,"Meter Pipe Connect failed\n"),fflush(stderr);
+                 DisplayErrorText(GetLastError());
+         }
+  }
+  pthread_exit(0);
+}
+
+PRIVATE void setup_meter_client()
+{
+//     fprintf(stderr,"Looking for the meter server\n"),fflush(stderr);
+       if (WaitNamedPipe(top.meas.mtr.path,INFINITE)) {
+//        fprintf(stderr,"Found the Meter server\n"),fflush(stderr);
+               if (INVALID_HANDLE_VALUE == (top.meas.mtr.fp = CreateFile(top.meas.mtr.path,
+                       GENERIC_READ, 0, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
+               {
+                       fprintf(stderr,"The Meter Client Open Failed\n"),fflush(stderr);
+                       DisplayErrorText(GetLastError());
+               } else {
+//                     fprintf(stderr,"The Meter Client Open Succeeded\n"),fflush(stderr);
+               }
+       } else {
+               fprintf(stderr,"Wait for meter pipe failed: Error message %d\n",GetLastError()),fflush(stderr);
+       }
+       sem_post(&setup_update_sem);
+       pthread_exit(0);
+}
+
+PRIVATE void setup_spec_server()
+{
+
+  if (INVALID_HANDLE_VALUE == (top.meas.spec.fd = CreateNamedPipe(top.meas.spec.path,
+                       PIPE_ACCESS_OUTBOUND,
+                       PIPE_WAIT|PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE,
+                       PIPE_UNLIMITED_INSTANCES,
+                       32768,
+                       32768,
+                       INFINITE,
+                       NULL)))
+  {
+         fprintf(stderr,"Spectrum pipe create failed\n"),fflush(stderr);
+         DisplayErrorText(GetLastError());
+  } else {
+//       fprintf(stderr,"Spectrum Pipe %s Create succeeded\n",top.meas.spec.path),fflush(stderr);
+         sem_post(&setup_update_sem);
+         if (ConnectNamedPipe(top.meas.spec.fd,NULL))
+         {
+//          fprintf(stderr,"Connected to the Spectrum Pipe\n"),fflush(stderr);
+         } else {
+                 fprintf(stderr,"Spectrum pipe connect failed\n"),fflush(stderr);
+                 DisplayErrorText(GetLastError());
+         }
+  }
+  pthread_exit(0);
+}
+
+PRIVATE void setup_spec_client()
+{
+//     fprintf(stderr,"Looking for the spectrum server\n"),fflush(stderr);
+       if (WaitNamedPipe(top.meas.spec.path,INFINITE)) {
+//             fprintf(stderr,"Found the server\n"),fflush(stderr);
+               if (INVALID_HANDLE_VALUE == (top.meas.spec.fp = CreateFile(top.meas.spec.path,
+                       GENERIC_READ, 0, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
+               {
+                       fprintf(stderr,"The Spectrum Client Open Failed\n"),fflush(stderr);
+                       DisplayErrorText(GetLastError());
+               } else {
+//                     fprintf(stderr,"The Spectrum Client Open Succeeded\n");
+//                     fprintf(stderr,"Spec Read handle = %08X\n",(DWORD)top.meas.spec.fp),fflush(stderr);
+               }
+       } else {
+               fprintf(stderr,"Wait for spec pipe failed\n"),fflush(stderr);
+               DisplayErrorText(GetLastError());
+       }
+       sem_post(&setup_update_sem);
+       pthread_exit(0);
+}
+PRIVATE pthread_t id1,id2,id3,id4,id5,id6;
+PRIVATE void 
+setup_updates(void) {
+
+  char mesg[16384]="TEST TEST METER\n";
+//  DWORD NumBytes;
+  top.parm.path = loc.path.parm;
+  sem_init(&setup_update_sem, 0, 0);
+  
+
+  if (uni.meter.flag) {
+    top.meas.mtr.path = loc.path.meter;
+  }
+  if (uni.spec.flag) {
+    top.meas.spec.path = loc.path.spec;
+  }
+
+   
+         // Do this STUPID stuff to make use of the Named Pipe Mechanism in Windows
+         // For the update server
+
+       
+  pthread_create(&id1, NULL, (void *) setup_update_server, NULL);
+  sem_wait(&setup_update_sem);
+  pthread_create(&id2, NULL, (void *) setup_update_client, NULL);
+  sem_wait(&setup_update_sem);
+  if (uni.meter.flag) {
+         pthread_create(&id3, NULL, (void *) setup_meter_server, NULL);
+         sem_wait(&setup_update_sem);
+         pthread_create(&id4, NULL, (void *) setup_meter_client, NULL);
+         sem_wait(&setup_update_sem);
+/*       if (WriteFile(top.meas.mtr.fd,mesg,strlen(mesg)+1,&NumBytes,NULL))
+         {
+                 fprintf(stderr,"Meter Pipe write succeeded and wrote %lu bytes\n",NumBytes),fflush(stderr);
+         } else {
+                 fprintf(stderr,"Meter Pipe write failed\n"),fflush(stderr);
+                 DisplayErrorText(GetLastError());
+         }
+         if (ReadFile(top.meas.mtr.fp,mesg,256,&NumBytes,NULL))
+         {
+                 fprintf(stderr,"Meter Pipe read succeeded and %lu bytes read\n",NumBytes),fflush(stderr);
+                 fprintf(stderr,"Meter message %s",mesg),fflush(stderr);
+         } else {
+                 fprintf(stderr,"Meter Pipe read failed\n"),fflush(stderr);
+                 DisplayErrorText(GetLastError());
+         }*/
+         
+  }
+  if (uni.spec.flag) {
+         memset(mesg,0,16384);
+         pthread_create(&id5, NULL, (void *) setup_spec_server, NULL);
+         sem_wait(&setup_update_sem);
+         pthread_create(&id6, NULL, (void *) setup_spec_client, NULL);
+         sem_wait(&setup_update_sem);
+         Sleep(0);
+/*       if (WriteFile(top.meas.spec.fd,mesg,16384,&NumBytes,NULL))
+         {
+                 fprintf(stderr,"Spec Pipe write succeeded and wrote %lu bytes\n",NumBytes),fflush(stderr);
+         } else {
+                 fprintf(stderr,"Spec Pipe write failed\n"),fflush(stderr);
+                 DisplayErrorText(GetLastError());
+         }
+         fprintf(stderr,"Spec Read handle(2) = %08X\n",(DWORD)top.meas.spec.fp),fflush(stderr);
+         if (ReadFile(top.meas.spec.fp,mesg,16384,&NumBytes,NULL))
+         {
+                 fprintf(stderr,"Spec Pipe read succeeded and %lu bytes read\n",NumBytes),fflush(stderr);
+         } else {
+                 fprintf(stderr,"Spec Pipe read failed\n"),fflush(stderr);
+                 DisplayErrorText(GetLastError());
+         } */
+  }
+  sem_destroy(&setup_update_sem);
+}
+PRIVATE void 
+setup_system_audio(void) {
+       size_t ringsize;
+       void *usemem;
+       sprintf(top.jack.name, "sdr-%d", top.pid);
+       top.jack.size = uni.buflen;
+       ringsize = top.hold.size.bytes * loc.mult.ring+sizeof(ringb_t);
+       usemem = safealloc(ringsize,1,"Ring Input Left");
+       top.jack.ring.i.l = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
+
+       usemem = safealloc(ringsize,1,"Ring Input Right");
+       top.jack.ring.i.r = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
+
+       usemem = safealloc(ringsize,1,"Ring Output Left");
+       top.jack.ring.o.l = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
+
+       usemem = safealloc(ringsize,1,"Ring Output Right");
+       top.jack.ring.o.r = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
+
+       usemem = safealloc(ringsize,1,"Ring Input Left Auxiliary");
+       top.jack.auxr.i.l = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
+
+       usemem = safealloc(ringsize,1,"Ring Input Right Auxiliary");
+       top.jack.auxr.i.r = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
+
+       usemem = safealloc(ringsize,1,"Ring Output Left Auxiliary");
+       top.jack.auxr.o.l = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
+
+       usemem = safealloc(ringsize,1,"Ring Output Right Auxiliary");
+       top.jack.auxr.o.r = ringb_create(usemem,top.hold.size.bytes * loc.mult.ring);
+
+       ringb_clear(top.jack.ring.o.l, top.jack.size * sizeof(float));
+       ringb_clear(top.jack.ring.o.r, top.jack.size * sizeof(float));
+       ringb_clear(top.jack.auxr.o.l, top.jack.size * sizeof(float));
+       ringb_clear(top.jack.auxr.o.r, top.jack.size * sizeof(float));
+}
+
+PRIVATE void 
+setup_threading(void) {
+  sem_init(&top.sync.upd.sem, 0, 0);
+  pthread_create(&top.thrd.upd.id, NULL, (void *) process_updates_thread, NULL);
+  sem_init(&top.sync.buf.sem, 0, 0);
+  pthread_create(&top.thrd.trx.id, NULL, (void *) process_samples_thread, NULL);
+  sem_init(&top.sync.mon.sem, 0, 0);
+  pthread_create(&top.thrd.mon.id, NULL, (void *) monitor_thread, NULL);
+  if (uni.meter.flag) {
+    sem_init(&top.sync.mtr.sem, 0, 0);
+    pthread_create(&top.thrd.mtr.id, NULL, (void *) meter_thread, NULL);
+  }
+  if (uni.spec.flag) {
+    sem_init(&top.sync.pws.sem, 0, 0);
+    pthread_create(&top.thrd.pws.id, NULL, (void *) spectrum_thread, NULL);
+  }
+  cs = &csobj;
+  InitializeCriticalSection(cs);
+} 
+
+//========================================================================
+// hard defaults, then environment
+
+PRIVATE void
+setup_defaults(void) {
+  loc.name[0] = 0; // no default name for jack client
+  strcpy(loc.path.rcfile, RCBASE);
+  strcpy(loc.path.parm, PARMPATH);
+  strcpy(loc.path.meter, METERPATH);
+  strcpy(loc.path.spec, SPECPATH);
+  strcpy(loc.path.wisdom, WISDOMPATH);
+  loc.def.rate = DEFRATE;
+  loc.def.size = DEFSIZE;
+  loc.def.nrx = MAXRX;
+  loc.def.mode = DEFMODE;
+  loc.def.spec = DEFSPEC;
+  loc.mult.ring = RINGMULT;
+}
+
+//========================================================================
+void 
+setup() {
+
+
+  top.pid = GetCurrentThreadId();
+  top.uid = 0L;
+  top.start_tv = now_tv();
+  top.running = TRUE;
+  top.verbose = FALSE;
+  top.state = RUN_PLAY;
+
+  setup_defaults();
+  top.verbose = FALSE;
+  uni.meter.flag = TRUE;
+  uni.spec.flag = TRUE;
+
+  setup_workspace();
+  setup_updates();
+
+  setup_local_audio();
+  setup_system_audio();
+
+  setup_threading();
+  setup_switching();
+    uni.spec.flag = TRUE;
+       uni.spec.type  = SPEC_POST_FILT;
+       uni.spec.scale = SPEC_PWR;
+       uni.spec.rxk = 0;
+
+}
+