Skip to content

Commit 816c565

Browse files
committed
add sndio support
1 parent fe6cba2 commit 816c565

File tree

3 files changed

+212
-12
lines changed

3 files changed

+212
-12
lines changed

Diff for: src/audio.c

+208-7
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,17 @@
7575
#include <sys/socket.h>
7676
#include <arpa/inet.h>
7777
#include <netinet/in.h>
78+
#include <errno.h>
7879

7980

8081
#if USE_ALSA
8182
#include <alsa/asoundlib.h>
82-
#else
83-
#include <errno.h>
84-
#ifdef __OpenBSD__
85-
#include <soundcard.h>
83+
#elif USE_SNDIO
84+
#include <sndio.h>
85+
#include <poll.h>
8686
#else
8787
#include <sys/soundcard.h>
8888
#endif
89-
#endif
9089

9190

9291
#include "audio.h"
@@ -111,6 +110,9 @@ static struct adev_s {
111110

112111
int bytes_per_frame; /* number of bytes for a sample from all channels. */
113112
/* e.g. 4 for stereo 16 bit. */
113+
#elif USE_SNDIO
114+
struct sio_hdl *sndio_in_handle;
115+
struct sio_hdl *sndio_out_handle;
114116

115117
#else
116118
int oss_audio_device_fd; /* Single device, both directions. */
@@ -141,6 +143,8 @@ static struct adev_s {
141143
#if USE_ALSA
142144
static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *name, char *dir);
143145
//static void alsa_select_device (char *pick_dev, int direction, char *result);
146+
#elif USE_SNDIO
147+
static int set_sndio_params (int a, struct sio_hdl *handle, struct audio_s *pa, char *devname, char *inout);
144148
#else
145149
static int set_oss_params (int a, int fd, struct audio_s *pa);
146150
#endif
@@ -212,7 +216,9 @@ static int calcbufsize(int rate, int chans, int bits)
212216

213217
int audio_open (struct audio_s *pa)
214218
{
219+
#if !USE_SNDIO
215220
int err;
221+
#endif
216222
int chan;
217223
int a;
218224
char audio_in_name[30];
@@ -224,7 +230,11 @@ int audio_open (struct audio_s *pa)
224230
memset (adev, 0, sizeof(adev));
225231

226232
for (a=0; a<MAX_ADEVS; a++) {
227-
#ifndef USE_ALSA
233+
#if USE_ALSA
234+
adev[a].audio_in_handle = adev[a].audio_out_handle = NULL;
235+
#elif USE_SNDIO
236+
adev[a].sndio_in_handle = adev[a].sndio_out_handle = NULL;
237+
#else
228238
adev[a].oss_audio_device_fd = -1;
229239
#endif
230240
adev[a].udp_sock = -1;
@@ -348,6 +358,24 @@ int audio_open (struct audio_s *pa)
348358

349359
adev[a].inbuf_size_in_bytes = set_alsa_params (a, adev[a].audio_in_handle, pa, audio_in_name, "input");
350360

361+
#elif USE_SNDIO
362+
adev[a].sndio_in_handle = sio_open (audio_in_name, SIO_REC, 0);
363+
if (adev[a].sndio_in_handle == NULL) {
364+
text_color_set(DW_COLOR_ERROR);
365+
dw_printf ("Could not open audio device %s for input\n",
366+
audio_in_name);
367+
return (-1);
368+
}
369+
370+
adev[a].inbuf_size_in_bytes = set_sndio_params (a, adev[a].sndio_in_handle, pa, audio_in_name, "input");
371+
372+
if (!sio_start (adev[a].sndio_in_handle)) {
373+
text_color_set(DW_COLOR_ERROR);
374+
dw_printf ("Could not start audio device %s for input\n",
375+
audio_in_name);
376+
return (-1);
377+
}
378+
351379
#else // OSS
352380
adev[a].oss_audio_device_fd = open (pa->adev[a].adevice_in, O_RDWR);
353381

@@ -439,6 +467,27 @@ int audio_open (struct audio_s *pa)
439467
return (-1);
440468
}
441469

470+
#elif USE_SNDIO
471+
adev[a].sndio_out_handle = sio_open (audio_out_name, SIO_PLAY, 0);
472+
if (adev[a].sndio_out_handle == NULL) {
473+
text_color_set(DW_COLOR_ERROR);
474+
dw_printf ("Could not open audio device %s for output\n",
475+
audio_out_name);
476+
return (-1);
477+
}
478+
479+
adev[a].outbuf_size_in_bytes = set_sndio_params (a, adev[a].sndio_out_handle, pa, audio_out_name, "output");
480+
481+
if (adev[a].inbuf_size_in_bytes <= 0 || adev[a].outbuf_size_in_bytes <= 0) {
482+
return (-1);
483+
}
484+
485+
if (!sio_start (adev[a].sndio_out_handle)) {
486+
text_color_set(DW_COLOR_ERROR);
487+
dw_printf ("Could not start audio device %s for output\n",
488+
audio_out_name);
489+
return (-1);
490+
}
442491
#endif
443492

444493
/*
@@ -675,6 +724,80 @@ static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *
675724
} /* end alsa_set_params */
676725

677726

727+
#elif USE_SNDIO
728+
729+
/*
730+
* Set parameters for sound card. (sndio)
731+
*
732+
* See /usr/include/sndio.h for details.
733+
*/
734+
735+
static int set_sndio_params (int a, struct sio_hdl *handle, struct audio_s *pa, char *devname, char *inout)
736+
{
737+
738+
struct sio_par q, r;
739+
740+
/* Signed 16 bit little endian or unsigned 8 bit. */
741+
sio_initpar (&q);
742+
q.bits = pa->adev[a].bits_per_sample;
743+
q.bps = (q.bits + 7) / 8;
744+
q.sig = (q.bits == 8) ? 0 : 1;
745+
q.le = 1; /* always little endian */
746+
q.msb = 0; /* LSB aligned */
747+
q.rchan = q.pchan = pa->adev[a].num_channels;
748+
q.rate = pa->adev[a].samples_per_sec;
749+
q.xrun = SIO_IGNORE;
750+
q.appbufsz = calcbufsize(pa->adev[a].samples_per_sec, pa->adev[a].num_channels, pa->adev[a].bits_per_sample);
751+
752+
753+
#if DEBUG
754+
text_color_set(DW_COLOR_DEBUG);
755+
dw_printf ("suggest buffer size %d bytes for %s %s.\n",
756+
q.appbufsz, devname, inout);
757+
#endif
758+
759+
/* challenge new setting */
760+
if (!sio_setpar (handle, &q)) {
761+
text_color_set(DW_COLOR_ERROR);
762+
dw_printf ("Could not set hardware parameter for %s %s.\n",
763+
devname, inout);
764+
return (-1);
765+
}
766+
767+
/* get response */
768+
if (!sio_getpar (handle, &r)) {
769+
text_color_set(DW_COLOR_ERROR);
770+
dw_printf ("Could not obtain current hardware setting for %s %s.\n",
771+
devname, inout);
772+
return (-1);
773+
}
774+
775+
#if DEBUG
776+
text_color_set(DW_COLOR_DEBUG);
777+
dw_printf ("audio buffer size %d bytes for %s %s.\n",
778+
r.appbufsz, devname, inout);
779+
#endif
780+
if (q.rate != r.rate) {
781+
text_color_set(DW_COLOR_INFO);
782+
dw_printf ("Asked for %d samples/sec but got %d for %s %s.",
783+
pa->adev[a].samples_per_sec, r.rate, devname, inout);
784+
pa->adev[a].samples_per_sec = r.rate;
785+
}
786+
787+
/* not supported */
788+
if (q.bits != r.bits || q.bps != r.bps || q.sig != r.sig ||
789+
(q.bits > 8 && q.le != r.le) ||
790+
(*inout == 'o' && q.pchan != r.pchan) ||
791+
(*inout == 'i' && q.rchan != r.rchan)) {
792+
text_color_set(DW_COLOR_ERROR);
793+
dw_printf ("Unsupported format for %s %s.\n", devname, inout);
794+
return (-1);
795+
}
796+
797+
return r.appbufsz;
798+
799+
} /* end set_sndio_params */
800+
678801
#else
679802

680803

@@ -842,7 +965,9 @@ __attribute__((hot))
842965
int audio_get (int a)
843966
{
844967
int n;
968+
#if USE_ALSA
845969
int retries = 0;
970+
#endif
846971

847972
#if STATISTICS
848973
/* Gather numbers for read from audio device. */
@@ -970,7 +1095,22 @@ int audio_get (int a)
9701095
}
9711096

9721097

973-
#else /* end ALSA, begin OSS */
1098+
#elif USE_SNDIO
1099+
1100+
while (adev[a].inbuf_next >= adev[a].inbuf_len) {
1101+
1102+
assert (adev[a].sndio_in_handle != NULL);
1103+
n = sio_read (adev[a].sndio_in_handle, adev[a].inbuf_ptr, adev[a].inbuf_size_in_bytes);
1104+
adev[a].inbuf_len = n;
1105+
adev[a].inbuf_next = 0;
1106+
1107+
audio_stats (a,
1108+
save_audio_config_p->adev[a].num_channels,
1109+
n / (save_audio_config_p->adev[a].num_channels * save_audio_config_p->adev[a].bits_per_sample / 8),
1110+
save_audio_config_p->statistics_interval);
1111+
}
1112+
1113+
#else /* begin OSS */
9741114

9751115
/* Fixed in 1.2. This was formerly outside of the switch */
9761116
/* so the OSS version did not process stdin or UDP. */
@@ -1250,6 +1390,30 @@ int audio_flush (int a)
12501390
adev[a].outbuf_len = 0;
12511391
return (-1);
12521392

1393+
#elif USE_SNDIO
1394+
1395+
int k;
1396+
unsigned char *ptr;
1397+
int len;
1398+
1399+
ptr = adev[a].outbuf_ptr;
1400+
len = adev[a].outbuf_len;
1401+
1402+
while (len > 0) {
1403+
assert (adev[a].sndio_out_handle != NULL);
1404+
k = sio_write (adev[a].sndio_out_handle, ptr, len);
1405+
#if DEBUGx
1406+
text_color_set(DW_COLOR_DEBUG);
1407+
dw_printf ("audio_flush(): write %d returns %d\n", len, k);
1408+
fflush (stdout);
1409+
#endif
1410+
ptr += k;
1411+
len -= k;
1412+
}
1413+
1414+
adev[a].outbuf_len = 0;
1415+
return (0);
1416+
12531417
#else /* OSS */
12541418

12551419
int k;
@@ -1351,6 +1515,28 @@ void audio_wait (int a)
13511515
* Either way, the caller will now compensate for it.
13521516
*/
13531517

1518+
#elif USE_SNDIO
1519+
1520+
struct pollfd *pfds;
1521+
int nfds, revents;
1522+
1523+
nfds = sio_nfds (adev[a].sndio_out_handle);
1524+
pfds = alloca (nfds * sizeof(struct pollfd));
1525+
1526+
do {
1527+
nfds = sio_pollfd (adev[a].sndio_out_handle, pfds, POLLOUT);
1528+
if (nfds < 1) {
1529+
/* no need to wait */
1530+
break;
1531+
}
1532+
if (poll (pfds, nfds, -1) < 0) {
1533+
text_color_set(DW_COLOR_ERROR);
1534+
dw_printf ("poll %d\n", errno);
1535+
break;
1536+
}
1537+
revents = sio_revents (adev[a].sndio_out_handle, pfds);
1538+
} while (!(revents & (POLLHUP | POLLOUT)));
1539+
13541540
#else
13551541

13561542
assert (adev[a].oss_audio_device_fd > 0);
@@ -1397,6 +1583,21 @@ int audio_close (void)
13971583
snd_pcm_close (adev[a].audio_in_handle);
13981584
snd_pcm_close (adev[a].audio_out_handle);
13991585

1586+
adev[a].audio_in_handle = adev[a].audio_out_handle = NULL;
1587+
1588+
#elif USE_SNDIO
1589+
1590+
if (adev[a].sndio_in_handle != NULL && adev[a].sndio_out_handle != NULL) {
1591+
1592+
audio_wait (a);
1593+
1594+
sio_stop (adev[a].sndio_in_handle);
1595+
sio_stop (adev[a].sndio_out_handle);
1596+
sio_close (adev[a].sndio_in_handle);
1597+
sio_close (adev[a].sndio_out_handle);
1598+
1599+
adev[a].sndio_in_handle = adev[a].sndio_out_handle = NULL;
1600+
14001601
#else
14011602

14021603
if (adev[a].oss_audio_device_fd > 0) {

Diff for: src/audio.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,8 @@ struct audio_s {
350350
#define DEFAULT_ADEVICE "" /* Mac OSX: Empty string = default audio device. */
351351
#elif USE_ALSA
352352
#define DEFAULT_ADEVICE "default" /* Use default device for ALSA. */
353-
#elif __OpenBSD__
354-
#define DEFAULT_ADEVICE "default" /* Use default device for OpenBSD-portaudio. */
353+
#elif USE_SNDIO
354+
#define DEFAULT_ADEVICE "default" /* Use default device for sndio. */
355355
#else
356356
#define DEFAULT_ADEVICE "/dev/dsp" /* First audio device for OSS. (FreeBSD) */
357357
#endif

Diff for: src/direwolf.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,8 @@
6767
#include <fcntl.h>
6868
#include <sys/types.h>
6969
#include <sys/ioctl.h>
70-
#ifdef __OpenBSD__
71-
#include <soundcard.h>
72-
#elif __APPLE__
70+
#if USE_SNDIO || __APPLE__
71+
// no need to include <soundcard.h>
7372
#else
7473
#include <sys/soundcard.h>
7574
#endif

0 commit comments

Comments
 (0)