| | |
| | | /* |
| | | Simple DirectMedia Layer |
| | | Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org> |
| | | Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> |
| | | |
| | | This software is provided 'as-is', without any express or implied |
| | | warranty. In no event will the authors be held liable for any damages |
| | |
| | | #include <signal.h> |
| | | #endif |
| | | |
| | | #include <poll.h> |
| | | #include <unistd.h> |
| | | |
| | | #include "SDL_audio.h" |
| | |
| | | #include "SDL_loadso.h" |
| | | #endif |
| | | |
| | | #ifndef INFTIM |
| | | #define INFTIM -1 |
| | | #endif |
| | | |
| | | #ifndef SIO_DEVANY |
| | | #define SIO_DEVANY "default" |
| | | #endif |
| | | |
| | | 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_stop)(struct sio_hdl *); |
| | | static size_t (*SNDIO_sio_read)(struct sio_hdl *, void *, size_t); |
| | | static size_t (*SNDIO_sio_write)(struct sio_hdl *, const void *, size_t); |
| | | static int (*SNDIO_sio_nfds)(struct sio_hdl *); |
| | | 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_eof)(struct sio_hdl *); |
| | | static void (*SNDIO_sio_initpar)(struct sio_par *); |
| | | |
| | | #ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC |
| | |
| | | SDL_SNDIO_SYM(sio_stop); |
| | | SDL_SNDIO_SYM(sio_read); |
| | | SDL_SNDIO_SYM(sio_write); |
| | | SDL_SNDIO_SYM(sio_nfds); |
| | | SDL_SNDIO_SYM(sio_pollfd); |
| | | SDL_SNDIO_SYM(sio_revents); |
| | | SDL_SNDIO_SYM(sio_eof); |
| | | SDL_SNDIO_SYM(sio_initpar); |
| | | return 0; |
| | | } |
| | |
| | | #endif |
| | | } |
| | | |
| | | static int |
| | | SNDIO_CaptureFromDevice(_THIS, void *buffer, int buflen) |
| | | { |
| | | size_t r; |
| | | int revents; |
| | | int nfds; |
| | | |
| | | /* Emulate a blocking read */ |
| | | r = SNDIO_sio_read(this->hidden->dev, buffer, buflen); |
| | | while (r == 0 && !SNDIO_sio_eof(this->hidden->dev)) { |
| | | if ((nfds = SNDIO_sio_pollfd(this->hidden->dev, this->hidden->pfd, POLLIN)) <= 0 |
| | | || poll(this->hidden->pfd, nfds, INFTIM) < 0) { |
| | | return -1; |
| | | } |
| | | revents = SNDIO_sio_revents(this->hidden->dev, this->hidden->pfd); |
| | | if (revents & POLLIN) { |
| | | r = SNDIO_sio_read(this->hidden->dev, buffer, buflen); |
| | | } |
| | | if (revents & POLLHUP) { |
| | | break; |
| | | } |
| | | } |
| | | return (int) r; |
| | | } |
| | | |
| | | 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) |
| | | { |
| | |
| | | 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); |
| | |
| | | |
| | | 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 ? devname : SIO_DEVANY, |
| | | 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); |
| | |
| | | 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. */ |
| | | } |