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);
}
}
}