diff --git a/audio/common/mmdevice_common.c b/audio/common/mmdevice_common.c index c30e0f5222..4070dfb14e 100644 --- a/audio/common/mmdevice_common.c +++ b/audio/common/mmdevice_common.c @@ -184,6 +184,58 @@ char *mmdevice_name(void *data) return result; } +void *mmdevice_handle(int id, unsigned data_flow) +{ + HRESULT hr; + IMMDeviceEnumerator *enumerator = NULL; + IMMDevice *device = NULL; + IMMDeviceCollection *collection = NULL; + const char *data_flow_name = mmdevice_data_flow_name(data_flow); +#ifdef __cplusplus + hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, + IID_IMMDeviceEnumerator, (void **)&enumerator); +#else + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, + &IID_IMMDeviceEnumerator, (void **)&enumerator); +#endif + if (FAILED(hr)) + return NULL; + hr = _IMMDeviceEnumerator_EnumAudioEndpoints(enumerator, + data_flow, DEVICE_STATE_ACTIVE, &collection); + if (FAILED(hr)) + { + RARCH_ERR("[MMDevice] Failed to enumerate audio endpoints: %s.\n", mmdevice_hresult_name(hr)); + goto error; + } + + hr = _IMMDeviceCollection_Item(collection, id, &device); + if (FAILED(hr)) + { + RARCH_ERR("[MMDevice] Failed to get IMMDevice #%d: %s.\n", id, mmdevice_hresult_name(hr)); + goto error; + } + + return device; + +error: + if (collection) +#ifdef __cplusplus + collection->Release(); +#else + collection->lpVtbl->Release(collection); +#endif + if (enumerator) +#ifdef __cplusplus + enumerator->Release(); +#else + enumerator->lpVtbl->Release(enumerator); +#endif + collection = NULL; + enumerator = NULL; + + return NULL; +} + void *mmdevice_init_device(const char *id, unsigned data_flow) { HRESULT hr; @@ -225,13 +277,14 @@ void *mmdevice_init_device(const char *id, unsigned data_flow) if (list->elems) { - /* If any devices were found... */ size_t d; + /* If any devices were found... */ for (d = 0; d < list->size; d++) { if (string_is_equal(id, list->elems[d].data)) { - RARCH_DBG("[MMDevice] Found device #%d: \"%s\".\n", d, list->elems[d].data); + RARCH_DBG("[MMDevice] Found device #%d: \"%s\".\n", d, + list->elems[d].data); idx_found = d; break; } @@ -242,7 +295,8 @@ void *mmdevice_init_device(const char *id, unsigned data_flow) if (idx_found == -1 && isdigit(id[0])) { idx_found = strtoul(id, NULL, 0); - RARCH_LOG("[MMDevice] Fallback, %s device index is a single number index instead: %u.\n", data_flow_name, idx_found); + RARCH_LOG("[MMDevice] Fallback, %s device index is a single number index instead: %u.\n", + data_flow_name, idx_found); } } string_list_free(list); diff --git a/audio/common/mmdevice_common.h b/audio/common/mmdevice_common.h index 1d911dc4e2..a46ecc1bfb 100644 --- a/audio/common/mmdevice_common.h +++ b/audio/common/mmdevice_common.h @@ -35,6 +35,11 @@ char* mmdevice_name(void *data); */ size_t mmdevice_samplerate(void *data); +/** + * Gets the handle of the IMMDevice. + */ +void *mmdevice_handle(int id, unsigned data_flow); + const char *mmdevice_hresult_name(int hr); diff --git a/audio/drivers/xaudio.c b/audio/drivers/xaudio.c index 43565d19c3..e983469e99 100644 --- a/audio/drivers/xaudio.c +++ b/audio/drivers/xaudio.c @@ -14,8 +14,9 @@ * If not, see . */ -#if !defined(_XBOX) && (_MSC_VER == 1310) +#if !defined(_XBOX) && (_MSC_VER == 1310) || defined(_MSC_VER) && (_WIN32_WINNT <= _WIN32_WINNT_WIN2K) #ifndef _WIN32_DCOM +/* needed for CoInitializeEx */ #define _WIN32_DCOM #endif #endif @@ -31,11 +32,6 @@ #include #include -#if defined(_MSC_VER) && (_WIN32_WINNT <= _WIN32_WINNT_WIN2K) -/* needed for CoInitializeEx */ -#define _WIN32_DCOM -#endif - #include "xaudio.h" #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600 /*_WIN32_WINNT_VISTA */) @@ -46,6 +42,7 @@ #ifdef HAVE_MMDEVICE #include "../common/mmdevice_common.h" +#include "../common/mmdevice_common_inline.h" #endif #include "../audio_driver.h" @@ -221,6 +218,27 @@ static const char *xaudio2_wave_format_name(WAVEFORMATEX *format) return ""; } +static size_t xa_device_get_samplerate(int id) +{ +#ifdef HAVE_MMDEVICE + IMMDevice *device = (IMMDevice*)mmdevice_handle(id, 0 /* eRender */); + if (device) + { + size_t _len = mmdevice_samplerate(device); +#ifdef __cplusplus + device->Release(); +#else + device->lpVtbl->Release(device); +#endif + return _len; + } +#else + /* TODO/FIXME - implement */ + (void)0; +#endif + return 0; +} + static xaudio2_t *xaudio2_new(unsigned *rate, unsigned channels, unsigned latency, size_t len, const char *dev_id) { @@ -277,22 +295,27 @@ static xaudio2_t *xaudio2_new(unsigned *rate, unsigned channels, { if (string_is_equal(dev_id, list->elems[i].data)) { + size_t new_rate = 0; RARCH_DBG("[XAudio2] Found device #%d: \"%s\".\n", i, list->elems[i].data); - idx_found = i; + idx_found = i; + new_rate = xa_device_get_samplerate(i); + if (new_rate > 0) + { + xaudio2_set_format(&desired_wf, true, channels, new_rate); + *rate = desired_wf.nSamplesPerSec; + } break; } } /* Index was not found yet based on name string, * just assume id is a one-character number index. */ - if (idx_found == -1) + if (idx_found == -1 && isdigit(dev_id[0])) { - if (isdigit(dev_id[0])) - { - idx_found = strtoul(dev_id, NULL, 0); - RARCH_LOG("[XAudio2] Fallback, device index is a single number index instead: %d.\n", idx_found); - } + idx_found = strtoul(dev_id, NULL, 0); + RARCH_LOG("[XAudio2] Fallback, device index is a single number index instead: %d.\n", + idx_found); } } }