From 4a50a04213b9f2c214702a77af3254f08f550c1b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 21 Oct 2018 22:40:17 -0400 Subject: [PATCH] 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 | 62 +++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index 731dcffb7fa9e..9d7c1591b38bd 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); }