audio: WaitDevice/WaitCaptureDevice now returns a result.

This is an attempt to centralize all the error handling, instead of
implicitly counting on WaitDevice implementations to disconnect the device
to report an error.
This commit is contained in:
Ryan C. Gordon
2023-10-03 10:35:18 -04:00
parent a0820ed833
commit d2d4914ac3
18 changed files with 85 additions and 57 deletions

View File

@@ -524,9 +524,9 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
// stubs for audio drivers that don't need a specific entry point... // stubs for audio drivers that don't need a specific entry point...
static void SDL_AudioThreadDeinit_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioThreadDeinit_Default(SDL_AudioDevice *device) { /* no-op. */ }
static void SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } static int SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ }
static int SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { return 0; /* no-op. */ } static int SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { return 0; /* no-op. */ }
static void SDL_AudioWaitCaptureDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } static int SDL_AudioWaitCaptureDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ }
static void SDL_AudioFlushCapture_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioFlushCapture_Default(SDL_AudioDevice *device) { /* no-op. */ }
static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */ }
static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ } static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ }
@@ -938,7 +938,10 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point
SDL_assert(!device->iscapture); SDL_assert(!device->iscapture);
SDL_OutputAudioThreadSetup(device); SDL_OutputAudioThreadSetup(device);
do { do {
current_audio.impl.WaitDevice(device); if (current_audio.impl.WaitDevice(device) < 0) {
SDL_AudioDeviceDisconnected(device); // doh.
break;
}
} while (SDL_OutputAudioThreadIterate(device)); } while (SDL_OutputAudioThreadIterate(device));
SDL_OutputAudioThreadShutdown(device); SDL_OutputAudioThreadShutdown(device);
@@ -1039,7 +1042,10 @@ static int SDLCALL CaptureAudioThread(void *devicep) // thread entry point
SDL_CaptureAudioThreadSetup(device); SDL_CaptureAudioThreadSetup(device);
do { do {
current_audio.impl.WaitCaptureDevice(device); if (current_audio.impl.WaitCaptureDevice(device) < 0) {
SDL_AudioDeviceDisconnected(device); // doh.
break;
}
} while (SDL_CaptureAudioThreadIterate(device)); } while (SDL_CaptureAudioThreadIterate(device));
SDL_CaptureAudioThreadShutdown(device); SDL_CaptureAudioThreadShutdown(device);

View File

@@ -128,10 +128,10 @@ typedef struct SDL_AudioDriverImpl
int (*OpenDevice)(SDL_AudioDevice *device); int (*OpenDevice)(SDL_AudioDevice *device);
void (*ThreadInit)(SDL_AudioDevice *device); // Called by audio thread at start void (*ThreadInit)(SDL_AudioDevice *device); // Called by audio thread at start
void (*ThreadDeinit)(SDL_AudioDevice *device); // Called by audio thread at end void (*ThreadDeinit)(SDL_AudioDevice *device); // Called by audio thread at end
void (*WaitDevice)(SDL_AudioDevice *device); int (*WaitDevice)(SDL_AudioDevice *device);
int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); // buffer and buflen are always from GetDeviceBuf, passed here for convenience. int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); // buffer and buflen are always from GetDeviceBuf, passed here for convenience.
Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size); Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size);
void (*WaitCaptureDevice)(SDL_AudioDevice *device); int (*WaitCaptureDevice)(SDL_AudioDevice *device);
int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen); int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen);
void (*FlushCapture)(SDL_AudioDevice *device); void (*FlushCapture)(SDL_AudioDevice *device);
void (*CloseDevice)(SDL_AudioDevice *device); void (*CloseDevice)(SDL_AudioDevice *device);

View File

@@ -164,9 +164,10 @@ static Uint8 *AAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize)
return &hidden->mixbuf[offset]; return &hidden->mixbuf[offset];
} }
static void AAUDIO_WaitDevice(SDL_AudioDevice *device) static int AAUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
SDL_WaitSemaphore(device->hidden->semaphore); SDL_WaitSemaphore(device->hidden->semaphore);
return 0;
} }
static int BuildAAudioStream(SDL_AudioDevice *device); static int BuildAAudioStream(SDL_AudioDevice *device);

View File

@@ -326,7 +326,7 @@ static void no_swizzle(SDL_AudioDevice *device, void *buffer, Uint32 bufferlen)
#endif // SND_CHMAP_API_VERSION #endif // SND_CHMAP_API_VERSION
// This function waits until it is possible to write a full sound buffer // This function waits until it is possible to write a full sound buffer
static void ALSA_WaitDevice(SDL_AudioDevice *device) static int ALSA_WaitDevice(SDL_AudioDevice *device)
{ {
const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq); const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq);
const int delay = SDL_max(fulldelay, 10); const int delay = SDL_max(fulldelay, 10);
@@ -338,9 +338,9 @@ static void ALSA_WaitDevice(SDL_AudioDevice *device)
if (status < 0) { if (status < 0) {
// Hmm, not much we can do - abort // Hmm, not much we can do - abort
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_wait failed (unrecoverable): %s", ALSA_snd_strerror(rc)); SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_wait failed (unrecoverable): %s", ALSA_snd_strerror(rc));
SDL_AudioDeviceDisconnected(device); return -1;
} }
return; continue;
} }
if (rc > 0) { if (rc > 0) {
@@ -349,6 +349,8 @@ static void ALSA_WaitDevice(SDL_AudioDevice *device)
// Timed out! Make sure we aren't shutting down and then wait again. // Timed out! Make sure we aren't shutting down and then wait again.
} }
return 0;
} }
static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)

View File

@@ -225,7 +225,7 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevi
} }
static void DSOUND_WaitDevice(SDL_AudioDevice *device) static int DSOUND_WaitDevice(SDL_AudioDevice *device)
{ {
/* Semi-busy wait, since we have no way of getting play notification /* Semi-busy wait, since we have no way of getting play notification
on a primary mixing buffer located in hardware (DirectX 5.0) on a primary mixing buffer located in hardware (DirectX 5.0)
@@ -251,12 +251,13 @@ static void DSOUND_WaitDevice(SDL_AudioDevice *device)
} }
if ((result != DS_OK) && (result != DSERR_BUFFERLOST)) { if ((result != DS_OK) && (result != DSERR_BUFFERLOST)) {
SDL_AudioDeviceDisconnected(device); return -1;
return;
} }
SDL_Delay(1); // not ready yet; sleep a bit. SDL_Delay(1); // not ready yet; sleep a bit.
} }
return 0;
} }
static int DSOUND_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) static int DSOUND_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
@@ -328,19 +329,20 @@ static Uint8 *DSOUND_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
return device->hidden->locked_buf; return device->hidden->locked_buf;
} }
static void DSOUND_WaitCaptureDevice(SDL_AudioDevice *device) static int DSOUND_WaitCaptureDevice(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
DWORD junk, cursor; DWORD junk, cursor;
if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) { if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) {
SDL_AudioDeviceDisconnected(device); return -1;
return;
} else if ((cursor / device->buffer_size) != h->lastchunk) { } else if ((cursor / device->buffer_size) != h->lastchunk) {
return; break;
} }
SDL_Delay(1); SDL_Delay(1);
} }
return 0;
} }
static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)

View File

@@ -35,9 +35,10 @@
#define DISKDEFAULT_INFILE "sdlaudio-in.raw" #define DISKDEFAULT_INFILE "sdlaudio-in.raw"
#define DISKENVR_IODELAY "SDL_DISKAUDIODELAY" #define DISKENVR_IODELAY "SDL_DISKAUDIODELAY"
static void DISKAUDIO_WaitDevice(SDL_AudioDevice *device) static int DISKAUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
SDL_Delay(device->hidden->io_delay); SDL_Delay(device->hidden->io_delay);
return 0;
} }
static int DISKAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) static int DISKAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)

View File

@@ -201,7 +201,7 @@ static int DSP_OpenDevice(SDL_AudioDevice *device)
return 0; // We're ready to rock and roll. :-) return 0; // We're ready to rock and roll. :-)
} }
static void DSP_WaitDevice(SDL_AudioDevice *device) static int DSP_WaitDevice(SDL_AudioDevice *device)
{ {
const unsigned long ioctlreq = device->iscapture ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE; const unsigned long ioctlreq = device->iscapture ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE;
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
@@ -215,14 +215,15 @@ static void DSP_WaitDevice(SDL_AudioDevice *device)
} }
// Hmm, not much we can do - abort // Hmm, not much we can do - abort
fprintf(stderr, "dsp WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno)); fprintf(stderr, "dsp WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno));
SDL_AudioDeviceDisconnected(device); return -1;
return;
} else if (info.bytes < device->buffer_size) { } else if (info.bytes < device->buffer_size) {
SDL_Delay(10); SDL_Delay(10);
} else { } else {
break; // ready to go! break; // ready to go!
} }
} }
return 0;
} }
static int DSP_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) static int DSP_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)

View File

@@ -28,9 +28,10 @@
// !!! FIXME: this should be an SDL hint, not an environment variable. // !!! FIXME: this should be an SDL hint, not an environment variable.
#define DUMMYENVR_IODELAY "SDL_DUMMYAUDIODELAY" #define DUMMYENVR_IODELAY "SDL_DUMMYAUDIODELAY"
static void DUMMYAUDIO_WaitDevice(SDL_AudioDevice *device) static int DUMMYAUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
SDL_Delay(device->hidden->io_delay); SDL_Delay(device->hidden->io_delay);
return 0;
} }
static int DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device) static int DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device)

View File

@@ -200,7 +200,7 @@ static int N3DSAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in
return 0; return 0;
} }
static void N3DSAUDIO_WaitDevice(SDL_AudioDevice *device) static int N3DSAUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
contextLock(device); contextLock(device);
while (!device->hidden->isCancelled && !SDL_AtomicGet(&device->shutdown) && while (!device->hidden->isCancelled && !SDL_AtomicGet(&device->shutdown) &&
@@ -208,6 +208,7 @@ static void N3DSAUDIO_WaitDevice(SDL_AudioDevice *device)
CondVar_Wait(&device->hidden->cv, &device->hidden->lock); CondVar_Wait(&device->hidden->cv, &device->hidden->lock);
} }
contextUnlock(device); contextUnlock(device);
return 0;
} }
static Uint8 *N3DSAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static Uint8 *N3DSAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)

View File

@@ -115,7 +115,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device)
#endif // DEBUG_AUDIO #endif // DEBUG_AUDIO
} }
static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
const SDL_bool iscapture = device->iscapture; const SDL_bool iscapture = device->iscapture;
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
@@ -127,8 +127,7 @@ static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
} }
// Hmm, not much we can do - abort // Hmm, not much we can do - abort
fprintf(stderr, "netbsdaudio WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno)); fprintf(stderr, "netbsdaudio WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno));
SDL_AudioDeviceDisconnected(device); return -1;
return;
} }
const size_t remain = (size_t)((iscapture ? info.record.seek : info.play.seek) * SDL_AUDIO_BYTESIZE(device->spec.format)); const size_t remain = (size_t)((iscapture ? info.record.seek : info.play.seek) * SDL_AUDIO_BYTESIZE(device->spec.format));
if (!iscapture && (remain >= device->buffer_size)) { if (!iscapture && (remain >= device->buffer_size)) {
@@ -139,6 +138,8 @@ static void NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
break; /* ready to go! */ break; /* ready to go! */
} }
} }
return 0;
} }
static int NETBSDAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) static int NETBSDAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)

View File

@@ -628,14 +628,14 @@ static int openslES_OpenDevice(SDL_AudioDevice *device)
return 0; return 0;
} }
static void openslES_WaitDevice(SDL_AudioDevice *device) static int openslES_WaitDevice(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *audiodata = device->hidden; struct SDL_PrivateAudioData *audiodata = device->hidden;
LOGV("openslES_WaitDevice()"); LOGV("openslES_WaitDevice()");
// Wait for an audio chunk to finish // Wait for an audio chunk to finish
SDL_WaitSemaphore(audiodata->playsem); return SDL_WaitSemaphore(audiodata->playsem);
} }
static int openslES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) static int openslES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)

View File

@@ -91,9 +91,10 @@ static int PS2AUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
return (audsrv_play_audio((char *)buffer, buflen) != buflen) ? -1 : 0; return (audsrv_play_audio((char *)buffer, buflen) != buflen) ? -1 : 0;
} }
static void PS2AUDIO_WaitDevice(SDL_AudioDevice *device) static int PS2AUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
audsrv_wait_audio(device->buffer_size); audsrv_wait_audio(device->buffer_size);
return 0;
} }
static Uint8 *PS2AUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static Uint8 *PS2AUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)

View File

@@ -118,9 +118,9 @@ static int PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
return (rc == 0) ? 0 : -1; return (rc == 0) ? 0 : -1;
} }
static void PSPAUDIO_WaitDevice(SDL_AudioDevice *device) static int PSPAUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
// Because we block when sending audio, there's no need for this function to do anything. return 0; // Because we block when sending audio, there's no need for this function to do anything.
} }
static Uint8 *PSPAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static Uint8 *PSPAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)

View File

@@ -396,9 +396,10 @@ static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata)
} }
/* This function waits until it is possible to write a full sound buffer */ /* This function waits until it is possible to write a full sound buffer */
static void PULSEAUDIO_WaitDevice(SDL_AudioDevice *device) static int PULSEAUDIO_WaitDevice(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
int retval = 0;
/*printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available);*/ /*printf("PULSEAUDIO PLAYDEVICE START! mixlen=%d\n", available);*/
@@ -410,11 +411,14 @@ static void PULSEAUDIO_WaitDevice(SDL_AudioDevice *device)
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
/*printf("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!\n");*/ /*printf("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!\n");*/
SDL_AudioDeviceDisconnected(device); retval = -1;
break; break;
} }
} }
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
return retval;
} }
static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
@@ -462,21 +466,23 @@ static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata)
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* the capture code queries what it needs, we just need to signal to end any wait */ PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); /* the capture code queries what it needs, we just need to signal to end any wait */
} }
static void PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
{ {
struct SDL_PrivateAudioData *h = device->hidden; struct SDL_PrivateAudioData *h = device->hidden;
if (h->capturebuf != NULL) { if (h->capturebuf != NULL) {
return; // there's still data available to read. return 0; // there's still data available to read.
} }
int retval = 0;
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
//printf("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!\n"); //printf("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!\n");
SDL_AudioDeviceDisconnected(device); retval = -1;
break; break;
} else if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) { } else if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) {
// a new fragment is available! // a new fragment is available!
@@ -497,6 +503,8 @@ static void PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device)
} }
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
return retval;
} }
static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)

View File

@@ -86,21 +86,19 @@ static void QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
} }
// This function waits until it is possible to write a full sound buffer // This function waits until it is possible to write a full sound buffer
static void QSA_WaitDevice(SDL_AudioDevice *device) static int QSA_WaitDevice(SDL_AudioDevice *device)
{ {
int result;
// Setup timeout for playing one fragment equal to 2 seconds // Setup timeout for playing one fragment equal to 2 seconds
// If timeout occurred than something wrong with hardware or driver // If timeout occurred than something wrong with hardware or driver
// For example, Vortex 8820 audio driver stucks on second DAC because // For example, Vortex 8820 audio driver stucks on second DAC because
// it doesn't exist ! // it doesn't exist !
result = SDL_IOReady(device->hidden->audio_fd, const int result = SDL_IOReady(device->hidden->audio_fd,
device->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE, device->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE,
2 * 1000); 2 * 1000);
switch (result) { switch (result) {
case -1: case -1:
SDL_SetError("QSA: SDL_IOReady() failed: %s", strerror(errno)); // !!! FIXME: Should we just disconnect the device in this case? SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "QSA: SDL_IOReady() failed: %s", strerror(errno));
break; return -1;
case 0: case 0:
device->hidden->timeout_on_wait = SDL_TRUE; // !!! FIXME: Should we just disconnect the device in this case? device->hidden->timeout_on_wait = SDL_TRUE; // !!! FIXME: Should we just disconnect the device in this case?
break; break;
@@ -108,6 +106,8 @@ static void QSA_WaitDevice(SDL_AudioDevice *device)
device->hidden->timeout_on_wait = SDL_FALSE; device->hidden->timeout_on_wait = SDL_FALSE;
break; break;
} }
return 0;
} }
static int QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) static int QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)

View File

@@ -147,32 +147,31 @@ static int LoadSNDIOLibrary(void)
#endif // SDL_AUDIO_DRIVER_SNDIO_DYNAMIC #endif // SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
static void SNDIO_WaitDevice(SDL_AudioDevice *device) static int SNDIO_WaitDevice(SDL_AudioDevice *device)
{ {
const SDL_bool iscapture = device->iscapture; const SDL_bool iscapture = device->iscapture;
while (!SDL_AtomicGet(&device->shutdown)) { while (!SDL_AtomicGet(&device->shutdown)) {
if (SNDIO_sio_eof(device->hidden->dev)) { if (SNDIO_sio_eof(device->hidden->dev)) {
SDL_AudioDeviceDisconnected(device); return -1;
return;
} }
const int nfds = SNDIO_sio_pollfd(device->hidden->dev, device->hidden->pfd, iscapture ? POLLIN : POLLOUT); const int nfds = SNDIO_sio_pollfd(device->hidden->dev, device->hidden->pfd, iscapture ? POLLIN : POLLOUT);
if (nfds <= 0 || poll(device->hidden->pfd, nfds, 10) < 0) { if (nfds <= 0 || poll(device->hidden->pfd, nfds, 10) < 0) {
SDL_AudioDeviceDisconnected(device); return -1;
return;
} }
const int revents = SNDIO_sio_revents(device->hidden->dev, device->hidden->pfd); const int revents = SNDIO_sio_revents(device->hidden->dev, device->hidden->pfd);
if (iscapture && (revents & POLLIN)) { if (iscapture && (revents & POLLIN)) {
return; break;
} else if (!iscapture && (revents & POLLOUT)) { } else if (!iscapture && (revents & POLLOUT)) {
return; break;
} else if (revents & POLLHUP) { } else if (revents & POLLHUP) {
SDL_AudioDeviceDisconnected(device); return -1;
return;
} }
} }
return 0;
} }
static int SNDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) static int SNDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)

View File

@@ -136,12 +136,13 @@ static int VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
} }
// This function waits until it is possible to write a full sound buffer // This function waits until it is possible to write a full sound buffer
static void VITAAUD_WaitDevice(SDL_AudioDevice *device) static int VITAAUD_WaitDevice(SDL_AudioDevice *device)
{ {
// !!! FIXME: we might just need to sleep roughly as long as playback buffers take to process, based on sample rate, etc. // !!! FIXME: we might just need to sleep roughly as long as playback buffers take to process, based on sample rate, etc.
while (!SDL_AtomicGet(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) { while (!SDL_AtomicGet(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) {
SDL_Delay(1); SDL_Delay(1);
} }
return 0;
} }
static Uint8 *VITAAUD_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static Uint8 *VITAAUD_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
@@ -172,7 +173,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device)
} }
} }
static void VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device) static int VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device)
{ {
// there's only a blocking call to obtain more data, so we'll just sleep as // there's only a blocking call to obtain more data, so we'll just sleep as
// long as a buffer would run. // long as a buffer would run.
@@ -180,6 +181,7 @@ static void VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device)
while (!SDL_AtomicGet(&device->shutdown) && (SDL_GetTicks() < endticks)) { while (!SDL_AtomicGet(&device->shutdown) && (SDL_GetTicks() < endticks)) {
SDL_Delay(1); SDL_Delay(1);
} }
return 0;
} }
static int VITAAUD_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int VITAAUD_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)

View File

@@ -431,7 +431,7 @@ static int WASAPI_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int b
return 0; return 0;
} }
static void WASAPI_WaitDevice(SDL_AudioDevice *device) static int WASAPI_WaitDevice(SDL_AudioDevice *device)
{ {
// WaitDevice does not hold the device lock, so check for recovery/disconnect details here. // WaitDevice does not hold the device lock, so check for recovery/disconnect details here.
while (RecoverWasapiIfLost(device) && device->hidden->client && device->hidden->event) { while (RecoverWasapiIfLost(device) && device->hidden->client && device->hidden->event) {
@@ -450,9 +450,11 @@ static void WASAPI_WaitDevice(SDL_AudioDevice *device)
} else if (waitResult != WAIT_TIMEOUT) { } else if (waitResult != WAIT_TIMEOUT) {
//SDL_Log("WASAPI FAILED EVENT!");*/ //SDL_Log("WASAPI FAILED EVENT!");*/
IAudioClient_Stop(device->hidden->client); IAudioClient_Stop(device->hidden->client);
WASAPI_DisconnectDevice(device); return -1;
} }
} }
return 0;
} }
static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)