Fixed bug 3705 - Add capture support to the sndio backend

kdrakehp

The attached patch adds capture support to the sndio backend.

The patch also allows the `OpenDevice' function to accept arbitrary device names.
This commit is contained in:
Sam Lantinga 2017-07-20 10:39:47 -07:00
parent 01050d4ed1
commit 2cc6806472
2 changed files with 67 additions and 3 deletions

View File

@ -33,6 +33,7 @@
#include <signal.h> #include <signal.h>
#endif #endif
#include <poll.h>
#include <unistd.h> #include <unistd.h>
#include "SDL_audio.h" #include "SDL_audio.h"
@ -47,6 +48,9 @@ static struct sio_hdl * (*SNDIO_sio_open)(const char *, unsigned int, int);
static void (*SNDIO_sio_close)(struct sio_hdl *); static void (*SNDIO_sio_close)(struct sio_hdl *);
static int (*SNDIO_sio_setpar)(struct sio_hdl *, struct sio_par *); static int (*SNDIO_sio_setpar)(struct sio_hdl *, struct sio_par *);
static int (*SNDIO_sio_getpar)(struct sio_hdl *, struct sio_par *); static int (*SNDIO_sio_getpar)(struct sio_hdl *, struct sio_par *);
static int (*SNDIO_sio_pollfd)(struct sio_hdl *, struct pollfd *, int);
static int (*SNDIO_sio_revents)(struct sio_hdl *, struct pollfd *);
static int (*SNDIO_sio_nfds)(struct sio_hdl *);
static int (*SNDIO_sio_start)(struct sio_hdl *); static int (*SNDIO_sio_start)(struct sio_hdl *);
static int (*SNDIO_sio_stop)(struct sio_hdl *); static int (*SNDIO_sio_stop)(struct sio_hdl *);
static size_t (*SNDIO_sio_read)(struct sio_hdl *, void *, size_t); static size_t (*SNDIO_sio_read)(struct sio_hdl *, void *, size_t);
@ -83,6 +87,9 @@ load_sndio_syms(void)
SDL_SNDIO_SYM(sio_close); SDL_SNDIO_SYM(sio_close);
SDL_SNDIO_SYM(sio_setpar); SDL_SNDIO_SYM(sio_setpar);
SDL_SNDIO_SYM(sio_getpar); SDL_SNDIO_SYM(sio_getpar);
SDL_SNDIO_SYM(sio_pollfd);
SDL_SNDIO_SYM(sio_nfds);
SDL_SNDIO_SYM(sio_revents);
SDL_SNDIO_SYM(sio_start); SDL_SNDIO_SYM(sio_start);
SDL_SNDIO_SYM(sio_stop); SDL_SNDIO_SYM(sio_stop);
SDL_SNDIO_SYM(sio_read); SDL_SNDIO_SYM(sio_read);
@ -164,6 +171,44 @@ SNDIO_PlayDevice(_THIS)
#endif #endif
} }
static int
SNDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
int revents;
int nfds;
int i;
int r;
/* Emulate a blocking read */
for (i = SNDIO_sio_read(this->hidden->dev, buffer, buflen); i < buflen;) {
if ((nfds = SNDIO_sio_pollfd(this->hidden->dev, this->hidden->pfd, POLLIN)) <= 0
|| poll(this->hidden->pfd, nfds, INFTIM) <= 0) {
break;
}
revents = SNDIO_sio_revents(this->hidden->dev, this->hidden->pfd);
if (revents & POLLIN) {
if ((r = SNDIO_sio_read(this->hidden->dev, (char *)buffer + i, buflen - i)) == 0) {
break;
}
i += r;
}
if (revents & POLLHUP) {
break;
}
}
return i;
}
static void
SNDIO_FlushCapture(_THIS)
{
char buf[512];
while (SNDIO_sio_read(this->hidden->dev, buf, sizeof(buf)) != 0) {
/* do nothing */;
}
}
static Uint8 * static Uint8 *
SNDIO_GetDeviceBuf(_THIS) SNDIO_GetDeviceBuf(_THIS)
{ {
@ -173,6 +218,9 @@ SNDIO_GetDeviceBuf(_THIS)
static void static void
SNDIO_CloseDevice(_THIS) SNDIO_CloseDevice(_THIS)
{ {
if ( this->hidden->pfd != NULL ) {
SDL_free(this->hidden->pfd);
}
if ( this->hidden->dev != NULL ) { if ( this->hidden->dev != NULL ) {
SNDIO_sio_stop(this->hidden->dev); SNDIO_sio_stop(this->hidden->dev);
SNDIO_sio_close(this->hidden->dev); SNDIO_sio_close(this->hidden->dev);
@ -197,11 +245,19 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
this->hidden->mixlen = this->spec.size; this->hidden->mixlen = this->spec.size;
/* !!! FIXME: SIO_DEVANY can be a specific device... */ /* Capture devices must be non-blocking for SNDIO_FlushCapture */
if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) { if ((this->hidden->dev =
SNDIO_sio_open(devname != NULL ? SIO_DEVANY : devname,
iscapture ? SIO_REC : SIO_PLAY, iscapture)) == NULL) {
return SDL_SetError("sio_open() failed"); return SDL_SetError("sio_open() failed");
} }
/* Allocate the pollfd array for capture devices */
if (iscapture && (this->hidden->pfd =
SDL_malloc(sizeof(struct pollfd) * SNDIO_sio_nfds(this->hidden->dev))) == NULL) {
return SDL_OutOfMemory();
}
SNDIO_sio_initpar(&par); SNDIO_sio_initpar(&par);
par.rate = this->spec.freq; par.rate = this->spec.freq;
@ -300,8 +356,12 @@ SNDIO_Init(SDL_AudioDriverImpl * impl)
impl->PlayDevice = SNDIO_PlayDevice; impl->PlayDevice = SNDIO_PlayDevice;
impl->GetDeviceBuf = SNDIO_GetDeviceBuf; impl->GetDeviceBuf = SNDIO_GetDeviceBuf;
impl->CloseDevice = SNDIO_CloseDevice; impl->CloseDevice = SNDIO_CloseDevice;
impl->CaptureFromDevice = SNDIO_CaptureFromDevice;
impl->FlushCapture = SNDIO_FlushCapture;
impl->Deinitialize = SNDIO_Deinitialize; impl->Deinitialize = SNDIO_Deinitialize;
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: sndio can handle multiple devices. */
impl->AllowsArbitraryDeviceNames = 1;
impl->HasCaptureSupport = SDL_TRUE;
return 1; /* this audio target is available. */ return 1; /* this audio target is available. */
} }

View File

@ -23,6 +23,7 @@
#ifndef _SDL_sndioaudio_h #ifndef _SDL_sndioaudio_h
#define _SDL_sndioaudio_h #define _SDL_sndioaudio_h
#include <poll.h>
#include <sndio.h> #include <sndio.h>
#include "../SDL_sysaudio.h" #include "../SDL_sysaudio.h"
@ -38,6 +39,9 @@ struct SDL_PrivateAudioData
/* Raw mixing buffer */ /* Raw mixing buffer */
Uint8 *mixbuf; Uint8 *mixbuf;
int mixlen; int mixlen;
/* Polling structures for non-blocking sndio devices */
struct pollfd *pfd;
}; };
#endif /* _SDL_sndioaudio_h */ #endif /* _SDL_sndioaudio_h */