Skip to content

add sndio support #313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add sndio support
  • Loading branch information
jg1uaa committed Feb 13, 2021
commit 816c5659f82a70663a258a1a16bb8b4e3378fb33
215 changes: 208 additions & 7 deletions src/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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. */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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];
Expand All @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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

/*
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions src/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions src/direwolf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down