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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c
index 731dcff..9d7c159 100644
--- a/src/audio/wasapi/SDL_wasapi_win32.c
+++ b/src/audio/wasapi/SDL_wasapi_win32.c
@@ -351,10 +351,42 @@ WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
}
+typedef struct
+{
+ LPWSTR devid;
+ char *devname;
+} EndpointItem;
+
+static int sort_endpoints(const void *_a, const void *_b)
+{
+ LPWSTR a = ((const EndpointItem *) _a)->devid;
+ LPWSTR b = ((const EndpointItem *) _b)->devid;
+ if (!a && b) {
+ return -1;
+ } else if (a && !b) {
+ return 1;
+ }
+
+ while (SDL_TRUE) {
+ if (*a < *b) {
+ return -1;
+ } else if (*a > *b) {
+ return 1;
+ } else if (*a == 0) {
+ break;
+ }
+ a++;
+ b++;
+ }
+
+ return 0;
+}
+
static void
WASAPI_EnumerateEndpointsForFlow(const SDL_bool iscapture)
{
IMMDeviceCollection *collection = NULL;
+ EndpointItem *items;
UINT i, total;
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
@@ -369,22 +401,36 @@ WASAPI_EnumerateEndpointsForFlow(const SDL_bool iscapture)
return;
}
+ items = (EndpointItem *) SDL_calloc(total, sizeof (EndpointItem));
+ if (!items) {
+ return; /* oh well. */
+ }
+
for (i = 0; i < total; i++) {
+ EndpointItem *item = items + i;
IMMDevice *device = NULL;
if (SUCCEEDED(IMMDeviceCollection_Item(collection, i, &device))) {
- LPWSTR devid = NULL;
- if (SUCCEEDED(IMMDevice_GetId(device, &devid))) {
- char *devname = GetWasapiDeviceName(device);
- if (devname) {
- WASAPI_AddDevice(iscapture, devname, devid);
- SDL_free(devname);
- }
- CoTaskMemFree(devid);
+ if (SUCCEEDED(IMMDevice_GetId(device, &item->devid))) {
+ item->devname = GetWasapiDeviceName(device);
}
IMMDevice_Release(device);
}
}
+ /* sort the list of devices by their guid so list is consistent between runs */
+ SDL_qsort(items, total, sizeof (*items), sort_endpoints);
+
+ /* Send the sorted list on to the SDL's higher level. */
+ for (i = 0; i < total; i++) {
+ EndpointItem *item = items + i;
+ if ((item->devid) && (item->devname)) {
+ WASAPI_AddDevice(iscapture, item->devname, item->devid);
+ }
+ SDL_free(item->devname);
+ CoTaskMemFree(item->devid);
+ }
+
+ SDL_free(items);
IMMDeviceCollection_Release(collection);
}