wasapi/win32: Sort initial device lists by device GUID.
authorRyan C. Gordon <icculus@icculus.org>
Sun, 21 Oct 2018 22:40:17 -0400
changeset 1234550e1cca28b39
parent 12344 9dd351b26dcb
child 12346 b4c98c84a0b2
wasapi/win32: Sort initial device lists by device GUID.

This makes an unchanged set of hardware always report devices in the same
order on each run.
src/audio/wasapi/SDL_wasapi_win32.c
     1.1 --- a/src/audio/wasapi/SDL_wasapi_win32.c	Sat Oct 20 21:35:48 2018 -0400
     1.2 +++ b/src/audio/wasapi/SDL_wasapi_win32.c	Sun Oct 21 22:40:17 2018 -0400
     1.3 @@ -351,10 +351,42 @@
     1.4  }
     1.5  
     1.6  
     1.7 +typedef struct
     1.8 +{
     1.9 +    LPWSTR devid;
    1.10 +    char *devname;
    1.11 +} EndpointItem;
    1.12 +
    1.13 +static int sort_endpoints(const void *_a, const void *_b)
    1.14 +{
    1.15 +    LPWSTR a = ((const EndpointItem *) _a)->devid;
    1.16 +    LPWSTR b = ((const EndpointItem *) _b)->devid;
    1.17 +    if (!a && b) {
    1.18 +        return -1;
    1.19 +    } else if (a && !b) {
    1.20 +        return 1;
    1.21 +    }
    1.22 +
    1.23 +    while (SDL_TRUE) {
    1.24 +        if (*a < *b) {
    1.25 +            return -1;
    1.26 +        } else if (*a > *b) {
    1.27 +            return 1;
    1.28 +        } else if (*a == 0) {
    1.29 +            break;
    1.30 +        }
    1.31 +        a++;
    1.32 +        b++;
    1.33 +    }
    1.34 +
    1.35 +    return 0;
    1.36 +}
    1.37 +
    1.38  static void
    1.39  WASAPI_EnumerateEndpointsForFlow(const SDL_bool iscapture)
    1.40  {
    1.41      IMMDeviceCollection *collection = NULL;
    1.42 +    EndpointItem *items;
    1.43      UINT i, total;
    1.44  
    1.45      /* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
    1.46 @@ -369,22 +401,36 @@
    1.47          return;
    1.48      }
    1.49  
    1.50 +    items = (EndpointItem *) SDL_calloc(total, sizeof (EndpointItem));
    1.51 +    if (!items) {
    1.52 +        return;  /* oh well. */
    1.53 +    }
    1.54 +
    1.55      for (i = 0; i < total; i++) {
    1.56 +        EndpointItem *item = items + i;
    1.57          IMMDevice *device = NULL;
    1.58          if (SUCCEEDED(IMMDeviceCollection_Item(collection, i, &device))) {
    1.59 -            LPWSTR devid = NULL;
    1.60 -            if (SUCCEEDED(IMMDevice_GetId(device, &devid))) {
    1.61 -                char *devname = GetWasapiDeviceName(device);
    1.62 -                if (devname) {
    1.63 -                    WASAPI_AddDevice(iscapture, devname, devid);
    1.64 -                    SDL_free(devname);
    1.65 -                }
    1.66 -                CoTaskMemFree(devid);
    1.67 +            if (SUCCEEDED(IMMDevice_GetId(device, &item->devid))) {
    1.68 +                item->devname = GetWasapiDeviceName(device);
    1.69              }
    1.70              IMMDevice_Release(device);
    1.71          }
    1.72      }
    1.73  
    1.74 +    /* sort the list of devices by their guid so list is consistent between runs */
    1.75 +    SDL_qsort(items, total, sizeof (*items), sort_endpoints);
    1.76 +
    1.77 +    /* Send the sorted list on to the SDL's higher level. */
    1.78 +    for (i = 0; i < total; i++) {
    1.79 +        EndpointItem *item = items + i;
    1.80 +        if ((item->devid) && (item->devname)) {
    1.81 +            WASAPI_AddDevice(iscapture, item->devname, item->devid);
    1.82 +        }
    1.83 +        SDL_free(item->devname);
    1.84 +        CoTaskMemFree(item->devid);
    1.85 +    }
    1.86 +
    1.87 +    SDL_free(items);
    1.88      IMMDeviceCollection_Release(collection);
    1.89  }
    1.90