diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index cef058f4a..def70906a 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -33,6 +33,7 @@ #include #endif +#include #include #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 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_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_stop)(struct sio_hdl *); 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_setpar); 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_stop); SDL_SNDIO_SYM(sio_read); @@ -164,6 +171,44 @@ SNDIO_PlayDevice(_THIS) #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 * SNDIO_GetDeviceBuf(_THIS) { @@ -173,6 +218,9 @@ SNDIO_GetDeviceBuf(_THIS) static void SNDIO_CloseDevice(_THIS) { + if ( this->hidden->pfd != NULL ) { + SDL_free(this->hidden->pfd); + } if ( this->hidden->dev != NULL ) { SNDIO_sio_stop(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; - /* !!! FIXME: SIO_DEVANY can be a specific device... */ - if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) { + /* Capture devices must be non-blocking for SNDIO_FlushCapture */ + 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"); } + /* 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); par.rate = this->spec.freq; @@ -300,8 +356,12 @@ SNDIO_Init(SDL_AudioDriverImpl * impl) impl->PlayDevice = SNDIO_PlayDevice; impl->GetDeviceBuf = SNDIO_GetDeviceBuf; impl->CloseDevice = SNDIO_CloseDevice; + impl->CaptureFromDevice = SNDIO_CaptureFromDevice; + impl->FlushCapture = SNDIO_FlushCapture; 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. */ } diff --git a/src/audio/sndio/SDL_sndioaudio.h b/src/audio/sndio/SDL_sndioaudio.h index a534b0a42..b20be1932 100644 --- a/src/audio/sndio/SDL_sndioaudio.h +++ b/src/audio/sndio/SDL_sndioaudio.h @@ -23,6 +23,7 @@ #ifndef _SDL_sndioaudio_h #define _SDL_sndioaudio_h +#include #include #include "../SDL_sysaudio.h" @@ -38,6 +39,9 @@ struct SDL_PrivateAudioData /* Raw mixing buffer */ Uint8 *mixbuf; int mixlen; + + /* Polling structures for non-blocking sndio devices */ + struct pollfd *pfd; }; #endif /* _SDL_sndioaudio_h */