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,9 @@ 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 );
148
+ static int poll_sndio (struct sio_hdl * hdl , int events );
144
149
#else
145
150
static int set_oss_params (int a , int fd , struct audio_s * pa );
146
151
#endif
@@ -212,7 +217,9 @@ static int calcbufsize(int rate, int chans, int bits)
212
217
213
218
int audio_open (struct audio_s * pa )
214
219
{
220
+ #if !USE_SNDIO
215
221
int err ;
222
+ #endif
216
223
int chan ;
217
224
int a ;
218
225
char audio_in_name [30 ];
@@ -224,7 +231,11 @@ int audio_open (struct audio_s *pa)
224
231
memset (adev , 0 , sizeof (adev ));
225
232
226
233
for (a = 0 ; a < MAX_ADEVS ; a ++ ) {
227
- #ifndef USE_ALSA
234
+ #if USE_ALSA
235
+ adev [a ].audio_in_handle = adev [a ].audio_out_handle = NULL ;
236
+ #elif USE_SNDIO
237
+ adev [a ].sndio_in_handle = adev [a ].sndio_out_handle = NULL ;
238
+ #else
228
239
adev [a ].oss_audio_device_fd = -1 ;
229
240
#endif
230
241
adev [a ].udp_sock = -1 ;
@@ -348,6 +359,24 @@ int audio_open (struct audio_s *pa)
348
359
349
360
adev [a ].inbuf_size_in_bytes = set_alsa_params (a , adev [a ].audio_in_handle , pa , audio_in_name , "input" );
350
361
362
+ #elif USE_SNDIO
363
+ adev [a ].sndio_in_handle = sio_open (audio_in_name , SIO_REC , 0 );
364
+ if (adev [a ].sndio_in_handle == NULL ) {
365
+ text_color_set (DW_COLOR_ERROR );
366
+ dw_printf ("Could not open audio device %s for input\n" ,
367
+ audio_in_name );
368
+ return (-1 );
369
+ }
370
+
371
+ adev [a ].inbuf_size_in_bytes = set_sndio_params (a , adev [a ].sndio_in_handle , pa , audio_in_name , "input" );
372
+
373
+ if (!sio_start (adev [a ].sndio_in_handle )) {
374
+ text_color_set (DW_COLOR_ERROR );
375
+ dw_printf ("Could not start audio device %s for input\n" ,
376
+ audio_in_name );
377
+ return (-1 );
378
+ }
379
+
351
380
#else // OSS
352
381
adev [a ].oss_audio_device_fd = open (pa -> adev [a ].adevice_in , O_RDWR );
353
382
@@ -439,6 +468,27 @@ int audio_open (struct audio_s *pa)
439
468
return (-1 );
440
469
}
441
470
471
+ #elif USE_SNDIO
472
+ adev [a ].sndio_out_handle = sio_open (audio_out_name , SIO_PLAY , 0 );
473
+ if (adev [a ].sndio_out_handle == NULL ) {
474
+ text_color_set (DW_COLOR_ERROR );
475
+ dw_printf ("Could not open audio device %s for output\n" ,
476
+ audio_out_name );
477
+ return (-1 );
478
+ }
479
+
480
+ adev [a ].outbuf_size_in_bytes = set_sndio_params (a , adev [a ].sndio_out_handle , pa , audio_out_name , "output" );
481
+
482
+ if (adev [a ].inbuf_size_in_bytes <= 0 || adev [a ].outbuf_size_in_bytes <= 0 ) {
483
+ return (-1 );
484
+ }
485
+
486
+ if (!sio_start (adev [a ].sndio_out_handle )) {
487
+ text_color_set (DW_COLOR_ERROR );
488
+ dw_printf ("Could not start audio device %s for output\n" ,
489
+ audio_out_name );
490
+ return (-1 );
491
+ }
442
492
#endif
443
493
444
494
/*
@@ -675,6 +725,112 @@ static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *
675
725
} /* end alsa_set_params */
676
726
677
727
728
+ #elif USE_SNDIO
729
+
730
+ /*
731
+ * Set parameters for sound card. (sndio)
732
+ *
733
+ * See /usr/include/sndio.h for details.
734
+ */
735
+
736
+ static int set_sndio_params (int a , struct sio_hdl * handle , struct audio_s * pa , char * devname , char * inout )
737
+ {
738
+
739
+ struct sio_par q , r ;
740
+
741
+ /* Signed 16 bit little endian or unsigned 8 bit. */
742
+ sio_initpar (& q );
743
+ q .bits = pa -> adev [a ].bits_per_sample ;
744
+ q .bps = (q .bits + 7 ) / 8 ;
745
+ q .sig = (q .bits == 8 ) ? 0 : 1 ;
746
+ q .le = 1 ; /* always little endian */
747
+ q .msb = 0 ; /* LSB aligned */
748
+ q .rchan = q .pchan = pa -> adev [a ].num_channels ;
749
+ q .rate = pa -> adev [a ].samples_per_sec ;
750
+ q .xrun = SIO_IGNORE ;
751
+ q .appbufsz = calcbufsize (pa -> adev [a ].samples_per_sec , pa -> adev [a ].num_channels , pa -> adev [a ].bits_per_sample );
752
+
753
+
754
+ #if DEBUG
755
+ text_color_set (DW_COLOR_DEBUG );
756
+ dw_printf ("suggest buffer size %d bytes for %s %s.\n" ,
757
+ q .appbufsz , devname , inout );
758
+ #endif
759
+
760
+ /* challenge new setting */
761
+ if (!sio_setpar (handle , & q )) {
762
+ text_color_set (DW_COLOR_ERROR );
763
+ dw_printf ("Could not set hardware parameter for %s %s.\n" ,
764
+ devname , inout );
765
+ return (-1 );
766
+ }
767
+
768
+ /* get response */
769
+ if (!sio_getpar (handle , & r )) {
770
+ text_color_set (DW_COLOR_ERROR );
771
+ dw_printf ("Could not obtain current hardware setting for %s %s.\n" ,
772
+ devname , inout );
773
+ return (-1 );
774
+ }
775
+
776
+ #if DEBUG
777
+ text_color_set (DW_COLOR_DEBUG );
778
+ dw_printf ("audio buffer size %d bytes for %s %s.\n" ,
779
+ r .appbufsz , devname , inout );
780
+ #endif
781
+ if (q .rate != r .rate ) {
782
+ text_color_set (DW_COLOR_INFO );
783
+ dw_printf ("Asked for %d samples/sec but got %d for %s %s." ,
784
+ pa -> adev [a ].samples_per_sec , r .rate , devname , inout );
785
+ pa -> adev [a ].samples_per_sec = r .rate ;
786
+ }
787
+
788
+ /* not supported */
789
+ if (q .bits != r .bits || q .bps != r .bps || q .sig != r .sig ||
790
+ (q .bits > 8 && q .le != r .le ) ||
791
+ (* inout == 'o' && q .pchan != r .pchan ) ||
792
+ (* inout == 'i' && q .rchan != r .rchan )) {
793
+ text_color_set (DW_COLOR_ERROR );
794
+ dw_printf ("Unsupported format for %s %s.\n" , devname , inout );
795
+ return (-1 );
796
+ }
797
+
798
+ return r .appbufsz ;
799
+
800
+ } /* end set_sndio_params */
801
+
802
+ static int poll_sndio (struct sio_hdl * hdl , int events )
803
+ {
804
+ struct pollfd * pfds ;
805
+ int nfds , revents ;
806
+
807
+ nfds = sio_nfds (hdl );
808
+ pfds = alloca (nfds * sizeof (struct pollfd ));
809
+
810
+ do {
811
+ nfds = sio_pollfd (hdl , pfds , events );
812
+ if (nfds < 1 ) {
813
+ /* no need to wait */
814
+ return (0 );
815
+ }
816
+ if (poll (pfds , nfds , -1 ) < 0 ) {
817
+ text_color_set (DW_COLOR_ERROR );
818
+ dw_printf ("poll %d\n" , errno );
819
+ return (-1 );
820
+ }
821
+ revents = sio_revents (hdl , pfds );
822
+ } while (!(revents & (events | POLLHUP )));
823
+
824
+ /* unrecoverable error occured */
825
+ if (revents & POLLHUP ) {
826
+ text_color_set (DW_COLOR_ERROR );
827
+ dw_printf ("waited for %s, POLLHUP received\n" , (events & POLLIN ) ? "POLLIN" : "POLLOUT" );
828
+ return (-1 );
829
+ }
830
+
831
+ return (0 );
832
+ }
833
+
678
834
#else
679
835
680
836
@@ -842,7 +998,11 @@ __attribute__((hot))
842
998
int audio_get (int a )
843
999
{
844
1000
int n ;
1001
+ #if USE_ALSA
845
1002
int retries = 0 ;
1003
+ #elif USE_SNDIO
1004
+ int err ;
1005
+ #endif
846
1006
847
1007
#if STATISTICS
848
1008
/* Gather numbers for read from audio device. */
@@ -970,7 +1130,29 @@ int audio_get (int a)
970
1130
}
971
1131
972
1132
973
- #else /* end ALSA, begin OSS */
1133
+ #elif USE_SNDIO
1134
+
1135
+ while (adev [a ].inbuf_next >= adev [a ].inbuf_len ) {
1136
+
1137
+ assert (adev [a ].sndio_in_handle != NULL );
1138
+ err = poll_sndio (adev [a ].sndio_in_handle , POLLIN );
1139
+ if (err < 0 ) {
1140
+ adev [a ].inbuf_len = 0 ;
1141
+ adev [a ].inbuf_next = 0 ;
1142
+ return (-1 );
1143
+ }
1144
+
1145
+ n = sio_read (adev [a ].sndio_in_handle , adev [a ].inbuf_ptr , adev [a ].inbuf_size_in_bytes );
1146
+ adev [a ].inbuf_len = n ;
1147
+ adev [a ].inbuf_next = 0 ;
1148
+
1149
+ audio_stats (a ,
1150
+ save_audio_config_p -> adev [a ].num_channels ,
1151
+ n / (save_audio_config_p -> adev [a ].num_channels * save_audio_config_p -> adev [a ].bits_per_sample / 8 ),
1152
+ save_audio_config_p -> statistics_interval );
1153
+ }
1154
+
1155
+ #else /* begin OSS */
974
1156
975
1157
/* Fixed in 1.2. This was formerly outside of the switch */
976
1158
/* so the OSS version did not process stdin or UDP. */
@@ -1250,6 +1432,38 @@ int audio_flush (int a)
1250
1432
adev [a ].outbuf_len = 0 ;
1251
1433
return (-1 );
1252
1434
1435
+ #elif USE_SNDIO
1436
+
1437
+ int k ;
1438
+ unsigned char * ptr ;
1439
+ int len , err ;
1440
+
1441
+ ptr = adev [a ].outbuf_ptr ;
1442
+ len = adev [a ].outbuf_len ;
1443
+
1444
+ while (len > 0 ) {
1445
+ assert (adev [a ].sndio_out_handle != NULL );
1446
+ err = poll_sndio (adev [a ].sndio_out_handle , POLLOUT );
1447
+ if (err < 0 ) {
1448
+ text_color_set (DW_COLOR_ERROR );
1449
+ perror ("Can't write to audio device" );
1450
+ adev [a ].outbuf_len = 0 ;
1451
+ return (-1 );
1452
+ }
1453
+
1454
+ k = sio_write (adev [a ].sndio_out_handle , ptr , len );
1455
+ #if DEBUGx
1456
+ text_color_set (DW_COLOR_DEBUG );
1457
+ dw_printf ("audio_flush(): write %d returns %d\n" , len , k );
1458
+ fflush (stdout );
1459
+ #endif
1460
+ ptr += k ;
1461
+ len -= k ;
1462
+ }
1463
+
1464
+ adev [a ].outbuf_len = 0 ;
1465
+ return (0 );
1466
+
1253
1467
#else /* OSS */
1254
1468
1255
1469
int k ;
@@ -1351,6 +1565,10 @@ void audio_wait (int a)
1351
1565
* Either way, the caller will now compensate for it.
1352
1566
*/
1353
1567
1568
+ #elif USE_SNDIO
1569
+
1570
+ poll_sndio (adev [a ].sndio_out_handle , POLLOUT );
1571
+
1354
1572
#else
1355
1573
1356
1574
assert (adev [a ].oss_audio_device_fd > 0 );
@@ -1396,7 +1614,22 @@ int audio_close (void)
1396
1614
1397
1615
snd_pcm_close (adev [a ].audio_in_handle );
1398
1616
snd_pcm_close (adev [a ].audio_out_handle );
1399
-
1617
+
1618
+ adev [a ].audio_in_handle = adev [a ].audio_out_handle = NULL ;
1619
+
1620
+ #elif USE_SNDIO
1621
+
1622
+ if (adev [a ].sndio_in_handle != NULL && adev [a ].sndio_out_handle != NULL ) {
1623
+
1624
+ audio_wait (a );
1625
+
1626
+ sio_stop (adev [a ].sndio_in_handle );
1627
+ sio_stop (adev [a ].sndio_out_handle );
1628
+ sio_close (adev [a ].sndio_in_handle );
1629
+ sio_close (adev [a ].sndio_out_handle );
1630
+
1631
+ adev [a ].sndio_in_handle = adev [a ].sndio_out_handle = NULL ;
1632
+
1400
1633
#else
1401
1634
1402
1635
if (adev [a ].oss_audio_device_fd > 0 ) {
0 commit comments