summaryrefslogtreecommitdiff
path: root/Source/3rdParty/SDL2/src/audio/SDL_audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/3rdParty/SDL2/src/audio/SDL_audio.c')
-rw-r--r--Source/3rdParty/SDL2/src/audio/SDL_audio.c111
1 files changed, 83 insertions, 28 deletions
diff --git a/Source/3rdParty/SDL2/src/audio/SDL_audio.c b/Source/3rdParty/SDL2/src/audio/SDL_audio.c
index dcaebea..f4999f1 100644
--- a/Source/3rdParty/SDL2/src/audio/SDL_audio.c
+++ b/Source/3rdParty/SDL2/src/audio/SDL_audio.c
@@ -378,21 +378,57 @@ static int
add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
{
int retval = -1;
- const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
- SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
- if (item == NULL) {
- return -1;
- }
+ SDL_AudioDeviceItem *item;
+ const SDL_AudioDeviceItem *i;
+ int dupenum = 0;
SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
+ SDL_assert(name != NULL);
+ item = (SDL_AudioDeviceItem *) SDL_malloc(sizeof (SDL_AudioDeviceItem));
+ if (!item) {
+ return SDL_OutOfMemory();
+ }
+
+ item->original_name = SDL_strdup(name);
+ if (!item->original_name) {
+ SDL_free(item);
+ return SDL_OutOfMemory();
+ }
+
+ item->dupenum = 0;
+ item->name = item->original_name;
item->handle = handle;
- SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
SDL_LockMutex(current_audio.detectionLock);
+
+ for (i = *devices; i != NULL; i = i->next) {
+ if (SDL_strcmp(name, i->original_name) == 0) {
+ dupenum = i->dupenum + 1;
+ break; /* stop at the highest-numbered dupe. */
+ }
+ }
+
+ if (dupenum) {
+ const size_t len = SDL_strlen(name) + 16;
+ char *replacement = (char *) SDL_malloc(len);
+ if (!replacement) {
+ SDL_UnlockMutex(current_audio.detectionLock);
+ SDL_free(item->original_name);
+ SDL_free(item);
+ SDL_OutOfMemory();
+ return -1;
+ }
+
+ SDL_snprintf(replacement, len, "%s (%d)", name, dupenum + 1);
+ item->dupenum = dupenum;
+ item->name = replacement;
+ }
+
item->next = *devices;
*devices = item;
- retval = (*devCount)++;
+ retval = (*devCount)++; /* !!! FIXME: this should be an atomic increment */
+
SDL_UnlockMutex(current_audio.detectionLock);
return retval;
@@ -420,6 +456,11 @@ free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
if (item->handle != NULL) {
current_audio.impl.FreeDeviceHandle(item->handle);
}
+ /* these two pointers are the same if not a duplicate devname */
+ if (item->name != item->original_name) {
+ SDL_free(item->name);
+ }
+ SDL_free(item->original_name);
SDL_free(item);
}
*devices = NULL;
@@ -451,7 +492,11 @@ void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
SDL_assert(get_audio_device(device->id) == device);
if (!SDL_AtomicGet(&device->enabled)) {
- return;
+ return; /* don't report disconnects more than once. */
+ }
+
+ if (SDL_AtomicGet(&device->shutdown)) {
+ return; /* don't report disconnect if we're trying to close device. */
}
/* Ends the audio callback and mark the device as STOPPED, but the
@@ -651,7 +696,7 @@ SDL_RunAudio(void *devicep)
SDL_assert(!device->iscapture);
/* The audio mixing is always a high priority thread */
- SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
+ SDL_SetThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
/* Perform any thread setup */
device->threadid = SDL_ThreadID();
@@ -832,6 +877,8 @@ SDL_CaptureAudio(void *devicep)
}
}
+ current_audio.impl.PrepareToClose(device);
+
current_audio.impl.FlushCapture(device);
current_audio.impl.ThreadDeinit(device);
@@ -971,6 +1018,11 @@ clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *re
} else {
*devices = next;
}
+ /* these two pointers are the same if not a duplicate devname */
+ if (item->name != item->original_name) {
+ SDL_free(item->name);
+ }
+ SDL_free(item->original_name);
SDL_free(item);
}
item = next;
@@ -997,7 +1049,6 @@ SDL_GetNumAudioDevices(int iscapture)
if (!iscapture && current_audio.outputDevicesRemoved) {
clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
- current_audio.outputDevicesRemoved = SDL_FALSE;
}
retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
@@ -1054,16 +1105,14 @@ close_audio_device(SDL_AudioDevice * device)
return;
}
- if (device->id > 0) {
- SDL_AudioDevice *opendev = open_devices[device->id - 1];
- SDL_assert((opendev == device) || (opendev == NULL));
- if (opendev == device) {
- open_devices[device->id - 1] = NULL;
- }
- }
-
+ /* make sure the device is paused before we do anything else, so the
+ audio callback definitely won't fire again. */
+ current_audio.impl.LockDevice(device);
+ SDL_AtomicSet(&device->paused, 1);
SDL_AtomicSet(&device->shutdown, 1);
SDL_AtomicSet(&device->enabled, 0);
+ current_audio.impl.UnlockDevice(device);
+
if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL);
}
@@ -1074,6 +1123,14 @@ close_audio_device(SDL_AudioDevice * device)
SDL_free(device->work_buffer);
SDL_FreeAudioStream(device->stream);
+ if (device->id > 0) {
+ SDL_AudioDevice *opendev = open_devices[device->id - 1];
+ SDL_assert((opendev == device) || (opendev == NULL));
+ if (opendev == device) {
+ open_devices[device->id - 1] = NULL;
+ }
+ }
+
if (device->hidden != NULL) {
current_audio.impl.CloseDevice(device);
}
@@ -1118,8 +1175,9 @@ prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
}
case 1: /* Mono */
case 2: /* Stereo */
- case 4: /* surround */
- case 6: /* surround with center and lfe */
+ case 4: /* Quadrophonic */
+ case 6: /* 5.1 surround */
+ case 8: /* 7.1 surround */
break;
default:
SDL_SetError("Unsupported number of audio channels.");
@@ -1312,15 +1370,12 @@ open_audio_device(const char *devname, int iscapture,
build_stream = SDL_TRUE;
}
}
-
- /* !!! FIXME in 2.1: add SDL_AUDIO_ALLOW_SAMPLES_CHANGE flag?
- As of 2.0.6, we will build a stream to buffer the difference between
- what the app wants to feed and the device wants to eat, so everyone
- gets their way. In prior releases, SDL would force the callback to
- feed at the rate the device requested, adjusted for resampling.
- */
if (device->spec.samples != obtained->samples) {
- build_stream = SDL_TRUE;
+ if (allowed_changes & SDL_AUDIO_ALLOW_SAMPLES_CHANGE) {
+ obtained->samples = device->spec.samples;
+ } else {
+ build_stream = SDL_TRUE;
+ }
}
SDL_CalculateAudioSpec(obtained); /* recalc after possible changes. */