1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-23 15:22:09 +00:00

ao_wasapi: Support loading devices by name

Do an strstr match against the device description and, if we have only
a single match, take it. This works as long as the devices in the system
don't change, but it's not supposed to be reliable; if one wants
reliability, one uses the device ID string.

Formatting.
This commit is contained in:
Diogo Franco (Kovensky) 2013-07-21 13:18:05 -03:00 committed by wm4
parent ad6acddbcf
commit c62395dc09

View File

@ -43,6 +43,9 @@
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName,
0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20,
0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc,
0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20,
0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2);
#endif
#define RING_BUFFER_COUNT 64
@ -471,6 +474,7 @@ static int find_formats(struct ao *const ao)
}
}
}
if (ao->channels.num > 6) {
/* Maybe this is 5.1 hardware with no support for more. */
bits = start_bits;
@ -621,6 +625,31 @@ exit_label:
return namestr;
}
static char* get_device_desc(IMMDevice *pDevice) {
if (!pDevice) {
return NULL;
}
IPropertyStore *pProps = NULL;
char *desc = NULL;
HRESULT hr = IMMDevice_OpenPropertyStore(pDevice, STGM_READ, &pProps);
EXIT_ON_ERROR(hr);
PROPVARIANT devdesc;
PropVariantInit(&devdesc);
hr = IPropertyStore_GetValue(pProps, &PKEY_Device_DeviceDesc, &devdesc);
EXIT_ON_ERROR(hr);
desc = wstring_to_utf8(devdesc.pwszVal);
exit_label:
PropVariantClear(&devdesc);
SAFE_RELEASE(pProps, IPropertyStore_Release(pProps));
return desc;
}
// frees *idstr
static int device_id_match(char *idstr, char *candidate) {
if (idstr == NULL || candidate == NULL)
@ -710,6 +739,7 @@ exit_label:
static int enumerate_devices(void) {
HRESULT hr;
CoInitialize(NULL);
hr = enumerate_with_state("Active devices:", DEVICE_STATE_ACTIVE, 1);
EXIT_ON_ERROR(hr);
hr = enumerate_with_state("Unplugged devices:", DEVICE_STATE_UNPLUGGED, 0);
@ -723,17 +753,27 @@ exit_label:
return 1;
}
static HRESULT find_and_load_device(IMMDevice **ppDevice, int devno, char *devid) {
static HRESULT find_and_load_device(IMMDevice **ppDevice, char *search) {
HRESULT hr;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDeviceCollection *pDevices = NULL;
IMMDevice *pTempDevice = NULL;
LPWSTR deviceID = NULL;
char *end;
int devno = (int) strtol(search, &end, 10);
char *devid = NULL;
if (end == search || *end) {
devid = search;
}
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
&IID_IMMDeviceEnumerator, (void**)&pEnumerator);
EXIT_ON_ERROR(hr);
int search_err = 0;
if (devid == NULL) {
hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eRender,
DEVICE_STATE_ACTIVE, &pDevices);
@ -765,6 +805,8 @@ static HRESULT find_and_load_device(IMMDevice **ppDevice, int devno, char *devid
mp_msg(MSGT_AO, MSGL_V, "ao-wasapi: finding device %s\n", devid);
IMMDevice *prevDevice = NULL;
for (int i = 0; i < count; i++) {
hr = IMMDeviceCollection_Item(pDevices, i, &pTempDevice);
EXIT_ON_ERROR(hr);
@ -774,9 +816,29 @@ static HRESULT find_and_load_device(IMMDevice **ppDevice, int devno, char *devid
EXIT_ON_ERROR(hr);
break;
}
char *desc = get_device_desc(pTempDevice);
if (strstr(desc, devid)) {
if (deviceID) {
char *name;
if (!search_err) {
mp_msg(MSGT_AO, MSGL_ERR, "ao-wasapi: multiple matching devices found!\n");
name = get_device_name(prevDevice);
mp_msg(MSGT_AO, MSGL_ERR, "ao-wasapi: %s\n", name);
free(name);
search_err = 1;
}
name = get_device_name(pTempDevice);
mp_msg(MSGT_AO, MSGL_ERR, "ao-wasapi: %s\n", name);
free(name);
}
hr = IMMDevice_GetId(pTempDevice, &deviceID);
prevDevice = pTempDevice;
}
free(desc);
SAFE_RELEASE(pTempDevice, IMMDevice_Release(pTempDevice));
}
if (deviceID == NULL) {
mp_msg(MSGT_AO, MSGL_ERR, "ao-wasapi: could not find device %s!\n", devid);
}
@ -785,7 +847,7 @@ static HRESULT find_and_load_device(IMMDevice **ppDevice, int devno, char *devid
SAFE_RELEASE(pTempDevice, IMMDevice_Release(pTempDevice));
SAFE_RELEASE(pDevices, IMMDeviceCollection_Release(pDevices));
if (deviceID == NULL) {
if (deviceID == NULL || search_err) {
hr = E_NOTFOUND;
} else {
mp_msg(MSGT_AO, MSGL_V, "ao-wasapi: loading device %S\n", deviceID);
@ -846,21 +908,7 @@ static int thread_init(struct ao *ao)
mp_msg(MSGT_AO, MSGL_V, "ao-wasapi: default device ID: %s\n", id);
free(id);
} else {
int devno = -1;
char *devid = NULL;
if (state->opt_device[0] == '{') { // ID as printed by list
devid = state->opt_device;
} else { // assume integer
char *end;
devno = (int) strtol(state->opt_device, &end, 10);
if (*end != '\0' || devno < 0) {
mp_msg(MSGT_AO, MSGL_ERR, "ao-wasapi: invalid device number %s!", state->opt_device);
goto exit_label;
}
}
hr = find_and_load_device(&state->pDevice, devno, devid);
hr = find_and_load_device(&state->pDevice, state->opt_device);
}
EXIT_ON_ERROR(hr);