mirror of https://github.com/wb2osz/direwolf.git
				
				
				
			add sndio support
This commit is contained in:
		
							parent
							
								
									fe6cba2b0d
								
							
						
					
					
						commit
						816c5659f8
					
				
							
								
								
									
										215
									
								
								src/audio.c
								
								
								
								
							
							
						
						
									
										215
									
								
								src/audio.c
								
								
								
								
							| 
						 | 
				
			
			@ -75,18 +75,17 @@
 | 
			
		|||
#include <sys/socket.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if USE_ALSA
 | 
			
		||||
#include <alsa/asoundlib.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#ifdef __OpenBSD__
 | 
			
		||||
#include <soundcard.h>
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
#include <sndio.h>
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <sys/soundcard.h>
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "audio.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -111,6 +110,9 @@ static struct adev_s {
 | 
			
		|||
 | 
			
		||||
	int bytes_per_frame;		/* number of bytes for a sample from all channels. */
 | 
			
		||||
					/* e.g. 4 for stereo 16 bit. */
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
	struct sio_hdl *sndio_in_handle;
 | 
			
		||||
	struct sio_hdl *sndio_out_handle;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
	int oss_audio_device_fd;	/* Single device, both directions. */
 | 
			
		||||
| 
						 | 
				
			
			@ -141,6 +143,8 @@ static struct adev_s {
 | 
			
		|||
#if USE_ALSA
 | 
			
		||||
static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *name, char *dir);
 | 
			
		||||
//static void alsa_select_device (char *pick_dev, int direction, char *result);
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
static int set_sndio_params (int a, struct sio_hdl *handle, struct audio_s *pa, char *devname, char *inout);
 | 
			
		||||
#else
 | 
			
		||||
static int set_oss_params (int a, int fd, struct audio_s *pa);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -212,7 +216,9 @@ static int calcbufsize(int rate, int chans, int bits)
 | 
			
		|||
 | 
			
		||||
int audio_open (struct audio_s *pa)
 | 
			
		||||
{
 | 
			
		||||
#if !USE_SNDIO
 | 
			
		||||
	int err;
 | 
			
		||||
#endif
 | 
			
		||||
	int chan;
 | 
			
		||||
	int a;
 | 
			
		||||
	char audio_in_name[30];
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +230,11 @@ int audio_open (struct audio_s *pa)
 | 
			
		|||
	memset (adev, 0, sizeof(adev));
 | 
			
		||||
 | 
			
		||||
	for (a=0; a<MAX_ADEVS; a++) {
 | 
			
		||||
#ifndef USE_ALSA
 | 
			
		||||
#if USE_ALSA
 | 
			
		||||
	  adev[a].audio_in_handle = adev[a].audio_out_handle = NULL;
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
	  adev[a].sndio_in_handle = adev[a].sndio_out_handle = NULL;
 | 
			
		||||
#else
 | 
			
		||||
	  adev[a].oss_audio_device_fd = -1;
 | 
			
		||||
#endif
 | 
			
		||||
	  adev[a].udp_sock = -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -348,6 +358,24 @@ int audio_open (struct audio_s *pa)
 | 
			
		|||
 | 
			
		||||
	        adev[a].inbuf_size_in_bytes = set_alsa_params (a, adev[a].audio_in_handle, pa, audio_in_name, "input");
 | 
			
		||||
	    
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
		adev[a].sndio_in_handle = sio_open (audio_in_name, SIO_REC, 0);
 | 
			
		||||
		if (adev[a].sndio_in_handle == NULL) {
 | 
			
		||||
		  text_color_set(DW_COLOR_ERROR);
 | 
			
		||||
		  dw_printf ("Could not open audio device %s for input\n",
 | 
			
		||||
			audio_in_name);
 | 
			
		||||
		  return (-1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		adev[a].inbuf_size_in_bytes = set_sndio_params (a, adev[a].sndio_in_handle, pa, audio_in_name, "input");
 | 
			
		||||
 | 
			
		||||
		if (!sio_start (adev[a].sndio_in_handle)) {
 | 
			
		||||
		  text_color_set(DW_COLOR_ERROR);
 | 
			
		||||
		  dw_printf ("Could not start audio device %s for input\n",
 | 
			
		||||
			audio_in_name);
 | 
			
		||||
		  return (-1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#else // OSS
 | 
			
		||||
	        adev[a].oss_audio_device_fd = open (pa->adev[a].adevice_in, O_RDWR);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -439,6 +467,27 @@ int audio_open (struct audio_s *pa)
 | 
			
		|||
	      return (-1);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
	    adev[a].sndio_out_handle = sio_open (audio_out_name, SIO_PLAY, 0);
 | 
			
		||||
	    if (adev[a].sndio_out_handle == NULL) {
 | 
			
		||||
	      text_color_set(DW_COLOR_ERROR);
 | 
			
		||||
	      dw_printf ("Could not open audio device %s for output\n",
 | 
			
		||||
			audio_out_name);
 | 
			
		||||
	      return (-1);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    adev[a].outbuf_size_in_bytes = set_sndio_params (a, adev[a].sndio_out_handle, pa, audio_out_name, "output");
 | 
			
		||||
 | 
			
		||||
	    if (adev[a].inbuf_size_in_bytes <= 0 || adev[a].outbuf_size_in_bytes <= 0) {
 | 
			
		||||
	      return (-1);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    if (!sio_start (adev[a].sndio_out_handle)) {
 | 
			
		||||
	      text_color_set(DW_COLOR_ERROR);
 | 
			
		||||
	      dw_printf ("Could not start audio device %s for output\n",
 | 
			
		||||
			audio_out_name);
 | 
			
		||||
	      return (-1);
 | 
			
		||||
	    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -675,6 +724,80 @@ static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *
 | 
			
		|||
} /* end alsa_set_params */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Set parameters for sound card. (sndio)
 | 
			
		||||
 *
 | 
			
		||||
 * See  /usr/include/sndio.h  for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int set_sndio_params (int a, struct sio_hdl *handle, struct audio_s *pa, char *devname, char *inout)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	struct sio_par q, r;
 | 
			
		||||
 | 
			
		||||
	/* Signed 16 bit little endian or unsigned 8 bit. */
 | 
			
		||||
	sio_initpar (&q);
 | 
			
		||||
	q.bits = pa->adev[a].bits_per_sample;
 | 
			
		||||
	q.bps = (q.bits + 7) / 8;
 | 
			
		||||
	q.sig = (q.bits == 8) ? 0 : 1;
 | 
			
		||||
	q.le = 1; /* always little endian */
 | 
			
		||||
	q.msb = 0; /* LSB aligned */
 | 
			
		||||
	q.rchan = q.pchan = pa->adev[a].num_channels;
 | 
			
		||||
	q.rate = pa->adev[a].samples_per_sec;
 | 
			
		||||
	q.xrun = SIO_IGNORE;
 | 
			
		||||
	q.appbufsz = calcbufsize(pa->adev[a].samples_per_sec, pa->adev[a].num_channels, pa->adev[a].bits_per_sample);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	text_color_set(DW_COLOR_DEBUG);
 | 
			
		||||
	dw_printf ("suggest buffer size %d bytes for %s %s.\n",
 | 
			
		||||
		q.appbufsz, devname, inout);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* challenge new setting */
 | 
			
		||||
	if (!sio_setpar (handle, &q)) {
 | 
			
		||||
	  text_color_set(DW_COLOR_ERROR);
 | 
			
		||||
	  dw_printf ("Could not set hardware parameter for %s %s.\n",
 | 
			
		||||
		devname, inout);
 | 
			
		||||
	  return (-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* get response */
 | 
			
		||||
	if (!sio_getpar (handle, &r)) {
 | 
			
		||||
	  text_color_set(DW_COLOR_ERROR);
 | 
			
		||||
	  dw_printf ("Could not obtain current hardware setting for %s %s.\n",
 | 
			
		||||
		devname, inout);
 | 
			
		||||
	  return (-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	text_color_set(DW_COLOR_DEBUG);
 | 
			
		||||
	dw_printf ("audio buffer size %d bytes for %s %s.\n",
 | 
			
		||||
		r.appbufsz, devname, inout);
 | 
			
		||||
#endif
 | 
			
		||||
	if (q.rate != r.rate) {
 | 
			
		||||
	  text_color_set(DW_COLOR_INFO);
 | 
			
		||||
	  dw_printf ("Asked for %d samples/sec but got %d for %s %s.",
 | 
			
		||||
		     pa->adev[a].samples_per_sec, r.rate, devname, inout);
 | 
			
		||||
	  pa->adev[a].samples_per_sec = r.rate;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* not supported */
 | 
			
		||||
	if (q.bits != r.bits || q.bps != r.bps || q.sig != r.sig ||
 | 
			
		||||
	    (q.bits > 8 && q.le != r.le) ||
 | 
			
		||||
	    (*inout == 'o' && q.pchan != r.pchan) ||
 | 
			
		||||
	    (*inout == 'i' && q.rchan != r.rchan)) {
 | 
			
		||||
	  text_color_set(DW_COLOR_ERROR);
 | 
			
		||||
	  dw_printf ("Unsupported format for %s %s.\n", devname, inout);
 | 
			
		||||
	  return (-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r.appbufsz;
 | 
			
		||||
 | 
			
		||||
} /* end set_sndio_params */
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -842,7 +965,9 @@ __attribute__((hot))
 | 
			
		|||
int audio_get (int a)
 | 
			
		||||
{
 | 
			
		||||
	int n;
 | 
			
		||||
#if USE_ALSA
 | 
			
		||||
	int retries = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if STATISTICS
 | 
			
		||||
	/* Gather numbers for read from audio device. */
 | 
			
		||||
| 
						 | 
				
			
			@ -970,7 +1095,22 @@ int audio_get (int a)
 | 
			
		|||
	    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else	/* end ALSA, begin OSS */
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
 | 
			
		||||
	    while (adev[a].inbuf_next >= adev[a].inbuf_len) {
 | 
			
		||||
 | 
			
		||||
	      assert (adev[a].sndio_in_handle != NULL);
 | 
			
		||||
	      n = sio_read (adev[a].sndio_in_handle, adev[a].inbuf_ptr, adev[a].inbuf_size_in_bytes);
 | 
			
		||||
	      adev[a].inbuf_len = n;
 | 
			
		||||
	      adev[a].inbuf_next = 0;
 | 
			
		||||
 | 
			
		||||
	      audio_stats (a,
 | 
			
		||||
			save_audio_config_p->adev[a].num_channels,
 | 
			
		||||
			n / (save_audio_config_p->adev[a].num_channels * save_audio_config_p->adev[a].bits_per_sample / 8),
 | 
			
		||||
			save_audio_config_p->statistics_interval);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
#else	/* begin OSS */
 | 
			
		||||
 | 
			
		||||
	    /* Fixed in 1.2.  This was formerly outside of the switch */
 | 
			
		||||
	    /* so the OSS version did not process stdin or UDP. */
 | 
			
		||||
| 
						 | 
				
			
			@ -1250,6 +1390,30 @@ int audio_flush (int a)
 | 
			
		|||
	adev[a].outbuf_len = 0;
 | 
			
		||||
	return (-1);
 | 
			
		||||
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
 | 
			
		||||
	int k;
 | 
			
		||||
	unsigned char *ptr;
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	ptr = adev[a].outbuf_ptr;
 | 
			
		||||
	len = adev[a].outbuf_len;
 | 
			
		||||
 | 
			
		||||
	while (len > 0) {
 | 
			
		||||
	  assert (adev[a].sndio_out_handle != NULL);
 | 
			
		||||
	  k = sio_write (adev[a].sndio_out_handle, ptr, len);
 | 
			
		||||
#if DEBUGx
 | 
			
		||||
	  text_color_set(DW_COLOR_DEBUG);
 | 
			
		||||
	  dw_printf ("audio_flush(): write %d returns %d\n", len, k);
 | 
			
		||||
	  fflush (stdout);
 | 
			
		||||
#endif
 | 
			
		||||
	  ptr += k;
 | 
			
		||||
	  len -= k;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	adev[a].outbuf_len = 0;
 | 
			
		||||
	return (0);
 | 
			
		||||
 | 
			
		||||
#else		/* OSS */
 | 
			
		||||
 | 
			
		||||
	int k;
 | 
			
		||||
| 
						 | 
				
			
			@ -1351,6 +1515,28 @@ void audio_wait (int a)
 | 
			
		|||
	 * Either way, the caller will now compensate for it.
 | 
			
		||||
 	 */
 | 
			
		||||
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
 | 
			
		||||
	struct pollfd *pfds;
 | 
			
		||||
	int nfds, revents;
 | 
			
		||||
 | 
			
		||||
	nfds = sio_nfds (adev[a].sndio_out_handle);
 | 
			
		||||
	pfds = alloca (nfds * sizeof(struct pollfd));
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
	  nfds = sio_pollfd (adev[a].sndio_out_handle, pfds, POLLOUT);
 | 
			
		||||
	  if (nfds < 1) {
 | 
			
		||||
	    /* no need to wait */
 | 
			
		||||
	    break;
 | 
			
		||||
	  }
 | 
			
		||||
	  if (poll (pfds, nfds, -1) < 0) {
 | 
			
		||||
	    text_color_set(DW_COLOR_ERROR);
 | 
			
		||||
	    dw_printf ("poll %d\n", errno);
 | 
			
		||||
	    break;
 | 
			
		||||
	  }
 | 
			
		||||
	  revents = sio_revents (adev[a].sndio_out_handle, pfds);
 | 
			
		||||
	} while (!(revents & (POLLHUP | POLLOUT)));
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	assert (adev[a].oss_audio_device_fd > 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -1397,6 +1583,21 @@ int audio_close (void)
 | 
			
		|||
	    snd_pcm_close (adev[a].audio_in_handle);
 | 
			
		||||
	    snd_pcm_close (adev[a].audio_out_handle);
 | 
			
		||||
	
 | 
			
		||||
	    adev[a].audio_in_handle = adev[a].audio_out_handle = NULL;
 | 
			
		||||
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
 | 
			
		||||
	  if (adev[a].sndio_in_handle != NULL && adev[a].sndio_out_handle != NULL) {
 | 
			
		||||
 | 
			
		||||
	    audio_wait (a);
 | 
			
		||||
 | 
			
		||||
	    sio_stop (adev[a].sndio_in_handle);
 | 
			
		||||
	    sio_stop (adev[a].sndio_out_handle);
 | 
			
		||||
	    sio_close (adev[a].sndio_in_handle);
 | 
			
		||||
	    sio_close (adev[a].sndio_out_handle);
 | 
			
		||||
 | 
			
		||||
	    adev[a].sndio_in_handle = adev[a].sndio_out_handle = NULL;
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	  if  (adev[a].oss_audio_device_fd > 0) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -350,8 +350,8 @@ struct audio_s {
 | 
			
		|||
#define DEFAULT_ADEVICE	""		/* Mac OSX: Empty string = default audio device. */
 | 
			
		||||
#elif USE_ALSA
 | 
			
		||||
#define DEFAULT_ADEVICE	"default"	/* Use default device for ALSA. */
 | 
			
		||||
#elif __OpenBSD__
 | 
			
		||||
#define DEFAULT_ADEVICE	"default"	/* Use default device for OpenBSD-portaudio. */
 | 
			
		||||
#elif USE_SNDIO
 | 
			
		||||
#define DEFAULT_ADEVICE	"default"	/* Use default device for sndio. */
 | 
			
		||||
#else
 | 
			
		||||
#define DEFAULT_ADEVICE	"/dev/dsp"	/* First audio device for OSS.  (FreeBSD) */
 | 
			
		||||
#endif					
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,9 +67,8 @@
 | 
			
		|||
#include <fcntl.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#ifdef __OpenBSD__
 | 
			
		||||
#include <soundcard.h>
 | 
			
		||||
#elif __APPLE__
 | 
			
		||||
#if USE_SNDIO || __APPLE__
 | 
			
		||||
// no need to include <soundcard.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <sys/soundcard.h>
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue