audio: All device names reported by SDL must be unique.
authorRyan C. Gordon <icculus@icculus.org>
Wed, 10 Oct 2018 15:20:56 -0400
changeset 123155ce13990c5fb
parent 12314 ddfb3da43e44
child 12316 e9954c42ee01
audio: All device names reported by SDL must be unique.

This means that if you have two devices named "Soundblaster Pro" in your
machine, one will be reported as "Soundblaster Pro" and the other as
"Soundblaster Pro (2)".

This makes it so you can't into a position where one of your devices can't
be opened because another is sitting on the same name.
src/audio/SDL_audio.c
src/audio/SDL_sysaudio.h
     1.1 --- a/src/audio/SDL_audio.c	Wed Oct 10 14:55:24 2018 -0400
     1.2 +++ b/src/audio/SDL_audio.c	Wed Oct 10 15:20:56 2018 -0400
     1.3 @@ -378,21 +378,57 @@
     1.4  add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
     1.5  {
     1.6      int retval = -1;
     1.7 -    const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
     1.8 -    SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
     1.9 -    if (item == NULL) {
    1.10 -        return -1;
    1.11 +    SDL_AudioDeviceItem *item;
    1.12 +    const SDL_AudioDeviceItem *i;
    1.13 +    int dupenum = 0;
    1.14 +
    1.15 +    SDL_assert(handle != NULL);  /* we reserve NULL, audio backends can't use it. */
    1.16 +    SDL_assert(name != NULL);
    1.17 +
    1.18 +    item = (SDL_AudioDeviceItem *) SDL_malloc(sizeof (SDL_AudioDeviceItem));
    1.19 +    if (!item) {
    1.20 +        return SDL_OutOfMemory();
    1.21      }
    1.22  
    1.23 -    SDL_assert(handle != NULL);  /* we reserve NULL, audio backends can't use it. */
    1.24 +    item->original_name = SDL_strdup(name);
    1.25 +    if (!item->original_name) {
    1.26 +        SDL_free(item);
    1.27 +        return SDL_OutOfMemory();
    1.28 +    }
    1.29  
    1.30 +    item->dupenum = 0;
    1.31 +    item->name = item->original_name;
    1.32      item->handle = handle;
    1.33 -    SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
    1.34  
    1.35      SDL_LockMutex(current_audio.detectionLock);
    1.36 +
    1.37 +    for (i = *devices; i != NULL; i = i->next) {
    1.38 +        if (SDL_strcmp(name, i->original_name) == 0) {
    1.39 +            dupenum = i->dupenum + 1;
    1.40 +            break;  /* stop at the highest-numbered dupe. */
    1.41 +        }
    1.42 +    }
    1.43 +
    1.44 +    if (dupenum) {
    1.45 +        const size_t len = SDL_strlen(name) + 16;
    1.46 +        char *replacement = (char *) SDL_malloc(len);
    1.47 +        if (!replacement) {
    1.48 +            SDL_UnlockMutex(current_audio.detectionLock);
    1.49 +            SDL_free(item->original_name);
    1.50 +            SDL_free(item);
    1.51 +            SDL_OutOfMemory();
    1.52 +            return -1;
    1.53 +        }
    1.54 +
    1.55 +        SDL_snprintf(replacement, len, "%s (%d)", name, dupenum + 1);
    1.56 +        item->dupenum = dupenum;
    1.57 +        item->name = replacement;
    1.58 +    }
    1.59 +
    1.60      item->next = *devices;
    1.61      *devices = item;
    1.62 -    retval = (*devCount)++;
    1.63 +    retval = (*devCount)++;   /* !!! FIXME: this should be an atomic increment */
    1.64 +
    1.65      SDL_UnlockMutex(current_audio.detectionLock);
    1.66  
    1.67      return retval;
    1.68 @@ -420,6 +456,11 @@
    1.69          if (item->handle != NULL) {
    1.70              current_audio.impl.FreeDeviceHandle(item->handle);
    1.71          }
    1.72 +        /* these two pointers are the same if not a duplicate devname */
    1.73 +        if (item->name != item->original_name) {
    1.74 +            SDL_free(item->name);
    1.75 +        }
    1.76 +        SDL_free(item->original_name);
    1.77          SDL_free(item);
    1.78      }
    1.79      *devices = NULL;
    1.80 @@ -977,6 +1018,11 @@
    1.81              } else {
    1.82                  *devices = next;
    1.83              }
    1.84 +            /* these two pointers are the same if not a duplicate devname */
    1.85 +            if (item->name != item->original_name) {
    1.86 +                SDL_free(item->name);
    1.87 +            }
    1.88 +            SDL_free(item->original_name);
    1.89              SDL_free(item);
    1.90          }
    1.91          item = next;
     2.1 --- a/src/audio/SDL_sysaudio.h	Wed Oct 10 14:55:24 2018 -0400
     2.2 +++ b/src/audio/SDL_sysaudio.h	Wed Oct 10 15:20:56 2018 -0400
     2.3 @@ -98,8 +98,10 @@
     2.4  typedef struct SDL_AudioDeviceItem
     2.5  {
     2.6      void *handle;
     2.7 +    char *name;
     2.8 +    char *original_name;
     2.9 +    int dupenum;
    2.10      struct SDL_AudioDeviceItem *next;
    2.11 -    char name[SDL_VARIABLE_LENGTH_ARRAY];
    2.12  } SDL_AudioDeviceItem;
    2.13  
    2.14