75
75
#include <sys/socket.h>
76
76
#include <arpa/inet.h>
77
77
#include <netinet/in.h>
78
+ #include <errno.h>
78
79
79
80
80
81
#if USE_ALSA
81
82
#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>
86
86
#else
87
87
#include <sys/soundcard.h>
88
88
#endif
89
- #endif
90
89
91
90
92
91
#include "audio.h"
@@ -111,6 +110,9 @@ static struct adev_s {
111
110
112
111
int bytes_per_frame ; /* number of bytes for a sample from all channels. */
113
112
/* 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 ;
114
116
115
117
#else
116
118
int oss_audio_device_fd ; /* Single device, both directions. */
@@ -141,6 +143,8 @@ static struct adev_s {
141
143
#if USE_ALSA
142
144
static int set_alsa_params (int a , snd_pcm_t * handle , struct audio_s * pa , char * name , char * dir );
143
145
//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 );
144
148
#else
145
149
static int set_oss_params (int a , int fd , struct audio_s * pa );
146
150
#endif
@@ -212,7 +216,9 @@ static int calcbufsize(int rate, int chans, int bits)
212
216
213
217
int audio_open (struct audio_s * pa )
214
218
{
219
+ #if !USE_SNDIO
215
220
int err ;
221
+ #endif
216
222
int chan ;
217
223
int a ;
218
224
char audio_in_name [30 ];
@@ -224,7 +230,11 @@ int audio_open (struct audio_s *pa)
224
230
memset (adev , 0 , sizeof (adev ));
225
231
226
232
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
228
238
adev [a ].oss_audio_device_fd = -1 ;
229
239
#endif
230
240
adev [a ].udp_sock = -1 ;
@@ -348,6 +358,24 @@ int audio_open (struct audio_s *pa)
348
358
349
359
adev [a ].inbuf_size_in_bytes = set_alsa_params (a , adev [a ].audio_in_handle , pa , audio_in_name , "input" );
350
360
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
+
351
379
#else // OSS
352
380
adev [a ].oss_audio_device_fd = open (pa -> adev [a ].adevice_in , O_RDWR );
353
381
@@ -439,6 +467,27 @@ int audio_open (struct audio_s *pa)
439
467
return (-1 );
440
468
}
441
469
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
+ }
442
491
#endif
443
492
444
493
/*
@@ -675,6 +724,80 @@ static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *
675
724
} /* end alsa_set_params */
676
725
677
726
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
+
678
801
#else
679
802
680
803
@@ -842,7 +965,9 @@ __attribute__((hot))
842
965
int audio_get (int a )
843
966
{
844
967
int n ;
968
+ #if USE_ALSA
845
969
int retries = 0 ;
970
+ #endif
846
971
847
972
#if STATISTICS
848
973
/* Gather numbers for read from audio device. */
@@ -970,7 +1095,22 @@ int audio_get (int a)
970
1095
}
971
1096
972
1097
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 */
974
1114
975
1115
/* Fixed in 1.2. This was formerly outside of the switch */
976
1116
/* so the OSS version did not process stdin or UDP. */
@@ -1250,6 +1390,30 @@ int audio_flush (int a)
1250
1390
adev [a ].outbuf_len = 0 ;
1251
1391
return (-1 );
1252
1392
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
+
1253
1417
#else /* OSS */
1254
1418
1255
1419
int k ;
@@ -1351,6 +1515,28 @@ void audio_wait (int a)
1351
1515
* Either way, the caller will now compensate for it.
1352
1516
*/
1353
1517
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
+
1354
1540
#else
1355
1541
1356
1542
assert (adev [a ].oss_audio_device_fd > 0 );
@@ -1397,6 +1583,21 @@ int audio_close (void)
1397
1583
snd_pcm_close (adev [a ].audio_in_handle );
1398
1584
snd_pcm_close (adev [a ].audio_out_handle );
1399
1585
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
+
1400
1601
#else
1401
1602
1402
1603
if (adev [a ].oss_audio_device_fd > 0 ) {
0 commit comments