923488792d
help from ratchov@
538 lines
15 KiB
Plaintext
538 lines
15 KiB
Plaintext
$OpenBSD: patch-src_server-main_C,v 1.2 2010/07/01 01:57:33 jakemsr Exp $
|
|
--- src/server-main.C.orig Wed Jun 30 17:19:24 2010
|
|
+++ src/server-main.C Wed Jun 30 17:35:40 2010
|
|
@@ -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(par.rate - 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
|