--- a/src/audio/bsd/SDL_bsdaudio.c Wed Aug 03 01:56:58 2016 -0400
+++ b/src/audio/bsd/SDL_bsdaudio.c Wed Aug 03 01:57:41 2016 -0400
@@ -63,13 +63,17 @@
#ifdef DEBUG_AUDIO
/* *INDENT-OFF* */
audio_info_t info;
+ const audio_prinfo *prinfo;
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
fprintf(stderr, "AUDIO_GETINFO failed.\n");
return;
}
+
+ prinfo = this->iscapture ? &info.play : &info.record;
+
fprintf(stderr, "\n"
- "[play/record info]\n"
+ "[%s info]\n"
"buffer size : %d bytes\n"
"sample rate : %i Hz\n"
"channels : %i\n"
@@ -83,18 +87,19 @@
"waiting : %s\n"
"active : %s\n"
"",
- info.play.buffer_size,
- info.play.sample_rate,
- info.play.channels,
- info.play.precision,
- info.play.encoding,
- info.play.seek,
- info.play.samples,
- info.play.eof,
- info.play.pause ? "yes" : "no",
- info.play.error ? "yes" : "no",
- info.play.waiting ? "yes" : "no",
- info.play.active ? "yes" : "no");
+ this->iscapture ? "record" : "play",
+ prinfo->buffer_size,
+ prinfo->sample_rate,
+ prinfo->channels,
+ prinfo->precision,
+ prinfo->encoding,
+ prinfo->seek,
+ prinfo->samples,
+ prinfo->eof,
+ prinfo->pause ? "yes" : "no",
+ prinfo->error ? "yes" : "no",
+ prinfo->waiting ? "yes" : "no",
+ prinfo->active ? "yes" : "no");
fprintf(stderr, "\n"
"[audio info]\n"
@@ -209,6 +214,57 @@
return (this->hidden->mixbuf);
}
+
+static int
+BSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
+{
+ Uint8 *buffer = (Uint8 *) _buffer;
+ int br, p = 0;
+
+ /* Write the audio data, checking for EAGAIN on broken audio drivers */
+ do {
+ br = read(this->hidden->audio_fd, buffer + p, buflen - p);
+ if (br > 0)
+ p += br;
+ if (br == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
+ /* Non recoverable error has occurred. It should be reported!!! */
+ perror("audio");
+ return p ? p : -1;
+ }
+
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "Captured %d bytes of audio data\n", br);
+#endif
+
+ if (p < buflen
+ || ((br < 0) && ((errno == 0) || (errno == EAGAIN)))) {
+ SDL_Delay(1); /* Let a little CPU time go by */
+ }
+ } while (p < buflen);
+}
+
+static void
+BSDAUDIO_FlushCapture(_THIS)
+{
+ audio_info_t info;
+ size_t remain;
+ Uint8 buf[512];
+
+ if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
+ return; /* oh well. */
+ }
+
+ remain = (size_t) (info.record.samples * (SDL_AUDIO_BITSIZE(this->spec.format) / 8));
+ while (remain > 0) {
+ const size_t len = SDL_min(sizeof (buf), remain);
+ const int br = read(this->hidden->audio_fd, buf, len);
+ if (br <= 0) {
+ return; /* oh well. */
+ }
+ remain -= br;
+ }
+}
+
static void
BSDAUDIO_CloseDevice(_THIS)
{
@@ -227,9 +283,10 @@
static int
BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
- const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
+ const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
SDL_AudioFormat format = 0;
audio_info_t info;
+ audio_prinfo *prinfo = iscapture ? &info.play : &info.record;
/* We don't care what the devname is...we'll try to open anything. */
/* ...but default to first name in the list... */
@@ -260,7 +317,7 @@
SDL_CalculateAudioSpec(&this->spec);
/* Set to play mode */
- info.mode = AUMODE_PLAY;
+ info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
BSDAUDIO_CloseDevice(this);
return SDL_SetError("Couldn't put device into play mode");
@@ -271,28 +328,28 @@
format; format = SDL_NextAudioFormat()) {
switch (format) {
case AUDIO_U8:
- info.play.encoding = AUDIO_ENCODING_ULINEAR;
- info.play.precision = 8;
+ prinfo->encoding = AUDIO_ENCODING_ULINEAR;
+ prinfo->precision = 8;
break;
case AUDIO_S8:
- info.play.encoding = AUDIO_ENCODING_SLINEAR;
- info.play.precision = 8;
+ prinfo->encoding = AUDIO_ENCODING_SLINEAR;
+ prinfo->precision = 8;
break;
case AUDIO_S16LSB:
- info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
- info.play.precision = 16;
+ prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ prinfo->precision = 16;
break;
case AUDIO_S16MSB:
- info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
- info.play.precision = 16;
+ prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ prinfo->precision = 16;
break;
case AUDIO_U16LSB:
- info.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
- info.play.precision = 16;
+ prinfo->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ prinfo->precision = 16;
break;
case AUDIO_U16MSB:
- info.play.encoding = AUDIO_ENCODING_ULINEAR_BE;
- info.play.precision = 16;
+ prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ prinfo->precision = 16;
break;
default:
continue;
@@ -311,26 +368,29 @@
this->spec.format = format;
AUDIO_INITINFO(&info);
- info.play.channels = this->spec.channels;
+ prinfo->channels = this->spec.channels;
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
this->spec.channels = 1;
}
AUDIO_INITINFO(&info);
- info.play.sample_rate = this->spec.freq;
+ prinfo->sample_rate = this->spec.freq;
info.blocksize = this->spec.size;
info.hiwat = 5;
info.lowat = 3;
(void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
(void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
- this->spec.freq = info.play.sample_rate;
- /* Allocate mixing buffer */
- this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
- if (this->hidden->mixbuf == NULL) {
- BSDAUDIO_CloseDevice(this);
- return SDL_OutOfMemory();
+ this->spec.freq = prinfo->sample_rate;
+
+ if (!iscapture) {
+ /* Allocate mixing buffer */
+ this->hidden->mixlen = this->spec.size;
+ this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+ if (this->hidden->mixbuf == NULL) {
+ BSDAUDIO_CloseDevice(this);
+ return SDL_OutOfMemory();
+ }
+ SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
}
- SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
BSDAUDIO_Status(this);
@@ -348,7 +408,10 @@
impl->WaitDevice = BSDAUDIO_WaitDevice;
impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
impl->CloseDevice = BSDAUDIO_CloseDevice;
+ impl->CaptureFromDevice = BSDAUDIO_CaptureFromDevice;
+ impl->FlushCapture = BSDAUDIO_FlushCapture;
+ impl->HasCaptureSupport = SDL_TRUE;
impl->AllowsArbitraryDeviceNames = 1;
return 1; /* this audio target is available. */