$OpenBSD: patch-src_server-main_C,v 1.3 2017/05/02 16:47:32 espie Exp $
Index: src/server-main.C
--- src/server-main.C.orig
+++ src/server-main.C
@@ -20,21 +20,14 @@
  */
 
 
-#include <sys/mman.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <sys/time.h>
 #include <fcntl.h>
-#include <sys/soundcard.h>
 #include <sys/ioctl.h>
+#include <poll.h>
 #include "psk31-receiver.h"
 #include "psk31-transmitter.h"
 #include "psk31-fft.h"
@@ -56,13 +49,15 @@
 #define RX 0
 
 // receive / transmit state information
-int full_duplex;
+int full_duplex = 0;
 int chans;
 int size;
 int bits;
-static char *audio_path="/dev/dsp";
+static char *audio_path=NULL;
 static char *ptt_path=NULL;
-static int audiofd=-1, pttfd=-1;
+static int pttfd=-1;
+static struct sio_hdl *hdl;
+static struct sio_par par;
 static int ptt_invert=0;
 static int ctl_ptt(int onoff);
 int scconfig[2];          /* [0]=8bit/16bit [1]=mono/stereo */
@@ -125,7 +120,16 @@ typedef struct
 #define N_BUFFERS 6
 static buffer_t buffers[N_BUFFERS];
 
+long long realpos, playpos;
 
+static void onmove(void *addr, int delta)
+{
+	struct sio_par *par = (struct sio_par *)addr;
+
+	realpos += delta * par->bps * par->pchan;
+}
+
+
 static void init_buffer()
 {
    int i;
@@ -203,216 +207,177 @@ buffer_t *b = buffers+bufnr;
  */
 int init_audio ()
 {
-   int val;
-   int speed = 8000;
+   uint speed = 8000;
    int frags;
+   int want_bits, want_chans, retval = 0;
 
    pthread_mutex_lock(&mutex_fd);  //get the mutex for soundcard fd
-   if (audiofd > 2)
+   if (hdl != NULL)
    {
-      close (audiofd);
-      usleep (50000);   //strange
-      audiofd = -1;
+      sio_close(hdl);
+      hdl = NULL;
    }
 
    /* Open the soundcard */
-   if (audiofd < 0)
+   if (hdl == NULL)
    {
       if (trDir == RX)
       {
-         audiofd = open(audio_path, O_RDONLY|O_NONBLOCK);
+	/* audio_path */
+         hdl = sio_open(NULL, SIO_REC, 0);
       }
       else
       {
-         audiofd = open(audio_path, O_WRONLY|O_NONBLOCK);
+         hdl = sio_open(NULL, SIO_PLAY, 0);
       }
    }
 
-   if (audiofd < 0)
+   if (hdl == NULL)
    {
-      fprintf (stderr, "init_audio: can't open %s\n", audio_path);
+      fprintf (stderr, "init_audio: can't open ");
+      if (audio_path == NULL)
+          fprintf (stderr, "default sndio device\n");
+      else
+          fprintf (stderr, "%s\n", audio_path);
       return -1;
    }
 
+   sio_initpar(&par);
+
    /* check parameter to see if 8 or 16 bits was requested */
    /* return 1 or 2 if set 8 or 16 bits format failed */
-   switch (scconfig[0])
+   want_bits = scconfig[0];
+   switch (want_bits)
    {
    case 0:    /* 8 bits requested */
-      val=AFMT_U8;
-      if (ioctl(audiofd, SNDCTL_DSP_SETFMT, &val) <0)
-      {
-         /* ioctl failed */
-         fprintf (stderr, "init_audio: ioctl SETFMT 8 failed\n");
-         return -1;
-      }
-
-      /* see if 8 bit worked */
-      if (val == AFMT_U8)
-      {
-         /* we can use 8 bit */
-         size = 1;
-         bits = 8;
-         // fprintf (stderr, "init_audio: trying 8 bit ");
-      }
-      else  /* 8 bit failed */
-      {
-         fprintf (stderr, "init_audio: failed to set to 8 bits\n");
-         return 1;
-      }
+      par.bits = 8;
+      par.sig = 0;
       break;
-
    case 1:    /* 16 bits requested */
-      val=AFMT_S16_NE;
-      if (ioctl(audiofd, SNDCTL_DSP_SETFMT, &val) <0)
-      {
-         /* ioctl failed */
-         fprintf (stderr, "init_audio: ioctl SETFMT 16 failed\n");
-         return -1;
-      }
-
-      /* see if 16 bit worked */
-      if (val == AFMT_S16_NE)
-      {
-         /* we can use 16 bit */
-         size = 2;
-         bits = 16;
-         // fprintf (stderr, "init_audio: trying 16 bit ");
-      }
-      else /* set 16 bit failed */
-      {
-         fprintf (stderr, "init_audio: failed to set to 16 bits\n");
-         return 2;
-      }
+      par.bits = 16;
+      par.sig = 1;
       break;
-   
-   default:  /* Invalid request */
-      fprintf (stderr, "\ninit_audio: invalid 8 or 16 bit request\n");
+   default:
+      fprintf (stderr, "\ninit_audio: invalid bit-depth request\n");
       return -1;
    }
 
    /* check parameter to see if MONO or STEREO was requested */
    /* return 3 or 4 if set mono or stereo format failed */
+   want_chans = scconfig[1];
    switch (scconfig[1])
    {
    case 0:  /* mono requested */
-      val=MONO;
-      if( ioctl(audiofd, SNDCTL_DSP_STEREO, &val)<0 )
-      {
-         /* ioctl failed */
-         fprintf (stderr,"\ninit_audio: ioctl failed - MONO\n");
-         return -1;
-      }
-      /* see if mono worked */
-      if (val == MONO)
-      {
-         /* we can use mono */
-         fprintf (stderr, "mono format\n");
-         chans = MONO;
-      }
+      if (trDir == RX)
+         par.rchan = 1;
       else
-      {
-         /* set mono failed */
-         fprintf (stderr, "\ninit_audio: request for mono failed\n");
-         return 3;
-      }
+         par.pchan = 1;
       break;
-
    case 1:   /* stereo request */
-      val = STEREO;
-      if( ioctl(audiofd, SNDCTL_DSP_STEREO, &val)<0 )
-      {
-         fprintf (stderr, "\ninit_audio: ioctl failed - STEREO\n");
-         return -1;
-      }
-      /* see if stereo worked */
-      if (val == STEREO)
-      {
-         /* we can use stereo */
-         fprintf (stderr, "stereo format\n");
-         size = size * 2;
-         chans = STEREO;
-      }
+      if (trDir == RX)
+         par.rchan = 2;
       else
-      {
-         /* set stereo failed */
-         fprintf (stderr, "\ninit_audio: request for stereo failed\n");
-         return 4;
-      }
+         par.pchan = 2;
       break;
-
    default:
-         fprintf (stderr, "\ninit_audio: invalid mono or stereo request\n");
-         return -1;
+      fprintf (stderr, "\ninit_audio: invalid mono or stereo request\n");
+      return -1;
    }
 
-   /* setup the rest */
-   val = speed;
-   if (ioctl(audiofd, SNDCTL_DSP_SPEED, &val) < 0)
+   if (want_bits == 0)
+      frags = 8;
+   else
+      frags = 10;
+
+   if (want_chans == 1)
+      frags++;
+
+   par.appbufsz = 1 << frags;
+
+   par.rate = speed;
+
+   if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par))
    {
-      fprintf (stderr, "init_audio: ioctl SPEED failed\n");
+      fprintf (stderr, "init_audio: error setting parameters\n");
       return -1;
    }
 
-   if (val == speed)
+   if (want_bits == 0 && (par.bits != 8 || par.sig != 0))
    {
-      fprintf (stderr,"init_audio: using %d sample rate\n", val);
+      fprintf (stderr, "init_audio: could not set 8-bit mode\n");
+      retval = 1;
    }
-   else
+   else if (want_bits == 1 && (par.bits != 16 || par.sig != 1))
    {
-      fprintf(stderr,"inexact sampling rate: "
-                     "request for %d resulted in %d\n",speed,val);
+      fprintf (stderr, "init_audio: could not set 16-bit mode\n");
+      retval = 2;
    }
 
-   if (bits == 8)
-      frags = 0x00020008;
+   if (par.bits == 8 && par.sig == 0)
+   {
+      size = 1;
+      bits = 8;
+   }
+   else if (par.bits == 16 && par.sig == 1)
+   {
+      size = 2;
+      bits = 16;
+   }
    else
-      frags = 0x0002000A;
+   {
+      fprintf (stderr, "init_audio: could not get usable format\n");
+      return -1;
+   }
 
-   if (chans == STEREO)
-      frags++;
+   if (want_chans == 0 &&
+    ((trDir == RX && par.rchan != 1) || (trDir == TX && par.pchan != 1)))
+   {
+      fprintf (stderr, "\ninit_audio: request for mono failed\n");
+      retval = 3;
+   }
+   else if (want_chans == 1 &&
+    ((trDir == RX && par.rchan != 2) || (trDir == TX && par.pchan != 2)))
+   {
+      fprintf (stderr, "\ninit_audio: request for stereo failed\n");
+      retval = 4;
+   }
 
-   val = frags;
-   ioctl(audiofd, SNDCTL_DSP_SETFRAGMENT, &val);
+   if ((trDir == RX && par.rchan == 1) || (trDir == TX && par.pchan == 1))
+   {
+      fprintf (stderr, "mono format\n");
+      chans = MONO;
+   }
+   else if ((trDir == RX && par.rchan == 2) || (trDir == TX && par.pchan == 2))
+   {
+      fprintf (stderr, "stereo format\n");
+      size = size * 2;
+      chans = STEREO;
+   }
 
-/*****************************************************/
-#if 0
-   audio_buf_info inInfo, outInfo;
-   if (ioctl(audiofd, SNDCTL_DSP_GETISPACE, &inInfo))
-      perror ("init_audio: SNDCTL_DSP_GETOSPACE");
-   if (ioctl(audiofd, SNDCTL_DSP_GETOSPACE, &outInfo))
-      perror ("init_audio: SNDCTL_DSP_GETOSPACE");
-
-printf ("In  fragments=0x%08x fragstotal=0x%08x fragsize=0x%08x\n",
-        inInfo.fragments, inInfo.fragstotal, inInfo.fragsize);
-printf ("Out fragments=0x%08x fragstotal=0x%08x fragsize=0x%08x\n",
-        outInfo.fragments, outInfo.fragstotal, outInfo.fragsize);
-#endif
-/*****************************************************/
-
-   // Check if the device is operating in full duplex mode
-   if( ioctl(audiofd, SNDCTL_DSP_GETCAPS, &val)<0 ) 
-      perror("Warning: GETCAPS on audio device failed");
+   if (abs(int(par.rate) - int(speed)) < speed * 1.03)
+   {
+      fprintf (stderr, "init_audio: using %d sample rate\n", speed);
+   }
    else
-      if(val&DSP_CAP_DUPLEX)
-         full_duplex=1;
-   fprintf(stderr,"init_audio: using %s duplex mode\n",
-           full_duplex ? "full" : "half");
+   {
+      fprintf(stderr, "could not set sampling rate: "
+                     "request for %d resulted in %d\n", speed, par.rate);
+      return -1;
+   }
 
-/*****************************************************/
-#if 0
-   val = 0;
-   if (ioctl(audiofd, SNDCTL_DSP_SETTRIGGER, &val) == -1)
-      perror("ioctl: SNDCTL_DSP_SETTRIGGER");
-   val = PCM_ENABLE_INPUT;
-   if (ioctl(audiofd, SNDCTL_DSP_SETTRIGGER, &val) == -1)
-      perror("ioctl: SNDCTL_DSP_SETTRIGGER");
-#endif
-/*****************************************************/
+   realpos = playpos = 0;
+   if (trDir == TX)
+      sio_onmove(hdl, onmove, &par);
 
+   if (!sio_start(hdl))
+   {
+      fprintf (stderr, "init_audio: could not start audio\n");
+      return -1;
+   }
+
    // fprintf (stderr, "init_audio: size=%d\n", size);
    pthread_mutex_unlock(&mutex_fd);
-   return 0;
+   return retval;
 }
 
 
@@ -461,10 +426,7 @@ static void *master_thr_func(void *dummy)
 void master_handler(void)
 {
    int res;
-   fd_set rset, wset, eset;
-   struct timeval tm;
    int dcd;
-   static short odd;
 
    buffers[COMM_RXCH].psk31rx->get_info(NULL,NULL,NULL,NULL,
                                         NULL,&dcd,NULL,NULL);
@@ -487,13 +449,6 @@ void master_handler(void)
       lastMode = trDir;
    }
 
-   FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
-   FD_SET(audiofd, &rset);
-   FD_SET(audiofd, &eset);
-   if (trDir == TX)
-      FD_SET(audiofd, &wset);
-   tm.tv_sec=0; tm.tv_usec=50000; /* 50ms */
-   res=select(audiofd+1, &rset, &wset, &eset, &tm);
    /* In my older version I had the problem, that there exist
     * sound drivers which do not support select correctly. So this
     * code tries to read/write from/to the audiodevice without
@@ -502,61 +457,54 @@ void master_handler(void)
 
    if (trDir == RX)
    {
-      short sample[2], save;
+      short buf[128];
+      int s = 0, todo;
+      char *p, *end;
 
-      for (;;)
-      {
-         pthread_mutex_lock (&mutex_fd);  // grab the mutex for the fd
-         odd++;
-         res = read(audiofd, &sample, size);
-         if (res == 0)
-         {
-            break;
-         }
-         else if (res != size)
-         {
-            // fprintf(stderr,"%d %d\n",res,errno);
-            if (errno == EINTR)
-            {
-               break;
-            }
-            if (errno == EAGAIN || errno == EBUSY)
-            {
-               break;
-            }
-            perror ("Audio read failed");
+      pthread_mutex_lock (&mutex_fd);  // grab the mutex for the fd
+      p = (char *)buf;
+      todo = sizeof(buf);
+      while (todo > 0) {
+         res = sio_read(hdl, p, todo);
+	 if (res == 0)
+	 {
+            fprintf (stderr, "Audio read failed");
             exit (1);
-         }
-         pthread_mutex_unlock (&mutex_fd);  // release mutex for fd
+	 }
+	 todo -= res;
+	 p += res;
+      }
+      pthread_mutex_unlock (&mutex_fd);  // release mutex for fd
 
+      for (p = (char *)buf, end = p + sizeof(buf); p < end;)
+      {
          /******* for S16_NE stereo *******/
          if (chans == STEREO && bits == 16)
          { 
             /* two signed 16 bits to one signed short */
-            sample[0] = sample[0] | sample[1];
+	    s = (((short *)p)[0] + ((short *)p)[1]) / 2;
+	    p += 2 * sizeof(short);
          }
 
          /******* for S16_NE mono *******/
          if (chans == MONO && bits == 16)
          { 
-           /* nothing to do for this one */
+	    s = ((short *)p)[0];
+	    p += sizeof(short);
          }
 
          /******* for U8 stereo *******/
          if (chans==STEREO && bits == 8)
          {
-            /* two unsigned 8 bit to a signed short */
-            save = (((sample[0]>>8)&0xFF) - 128) * 128;   //low
-            sample[0] = ((sample[0]&0xFF) - 128) * 128;   //high
-            sample[0] = sample[0] | save;                 //mixed
+	    s = 128 * (p[0] ^ 0x80) + (p[1] ^ 0x80);
+	    p += 2;
          }
 
          /******* for U8 mono *******/
          if (chans == MONO && bits == 8)
-         { 
-            /* unsigned 8 bit to signed short */
-            sample[0] = ((sample[0]&0xFF) - 128) * 128;
-
+         {
+	    s = 256 * (p[0] ^ 0x80);
+	    p++;
          }
 
         /*****************************/
@@ -569,7 +517,7 @@ void master_handler(void)
                pthread_mutex_unlock(&mutex_rx);
                continue;
             }
-            res = rx->process_rx_sample (sample[0]);
+            res = rx->process_rx_sample (s);
             pthread_mutex_unlock(&mutex_rx);
             if(res!=NO_CHAR)
             {
@@ -597,13 +545,14 @@ void master_handler(void)
             char buffer[128];
             for(;;)
             {
-               res=read(audiofd, buffer, 128);
+               res=sio_read(hdl, buffer, 128);
                if(res!=128) break;
             }
          }
 
          pthread_mutex_lock (&mutex_fd);
          pthread_mutex_lock(&mutex_tx);
+         psk31tx->set_audiofd(hdl);
          res=psk31tx->processor();
          pthread_mutex_unlock(&mutex_tx);
          pthread_mutex_unlock (&mutex_fd);
@@ -742,7 +691,7 @@ int server_main(char *audio, char *ptt, char *datadir)
    psk31fft->set_parameters(1024, 1024, psk31_fft::MODE_RXDATA);
    buffers[COMM_RXCH].psk31rx = new psk31_receiver(psk31fft);
    psk31tx = new psk31_transmitter();
-   psk31tx->set_audiofd(audiofd);
+   psk31tx->set_audiofd(hdl);
 
 
    #ifdef USE_PTHREAD
