[PATCH 13/29] dsound: Use mmdevice apis for enumerating capture devices
Maarten Lankhorst
m.b.lankhorst at gmail.com
Thu Apr 7 19:03:28 CDT 2011
---
dlls/dsound/Makefile.in | 2 +-
dlls/dsound/capture.c | 15 +---
dlls/dsound/dsound_main.c | 241 ++++++++++++++++++++++++++++++++----------
dlls/dsound/dsound_private.h | 12 ++-
dlls/dsound/propset.c | 150 ++++++++++++++++++++------
5 files changed, 314 insertions(+), 106 deletions(-)
diff --git a/dlls/dsound/Makefile.in b/dlls/dsound/Makefile.in
index 58b1998..8258637 100644
--- a/dlls/dsound/Makefile.in
+++ b/dlls/dsound/Makefile.in
@@ -1,6 +1,6 @@
MODULE = dsound.dll
IMPORTLIB = dsound
-IMPORTS = dxguid uuid winmm ole32 advapi32
+IMPORTS = dxguid uuid winmm ole32 advapi32 user32
C_SRCS = \
buffer.c \
diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c
index f089313..8b3fa54 100644
--- a/dlls/dsound/capture.c
+++ b/dlls/dsound/capture.c
@@ -1038,8 +1038,7 @@ static HRESULT DirectSoundCaptureDevice_Initialize(
LPCGUID lpcGUID)
{
HRESULT err = DSERR_INVALIDPARAM;
- unsigned wid, widn;
- BOOLEAN found = FALSE;
+ unsigned wid = 0, widn;
GUID devGUID;
DirectSoundCaptureDevice *device = *ppDevice;
TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
@@ -1060,18 +1059,6 @@ static HRESULT DirectSoundCaptureDevice_Initialize(
}
/* enumerate WINMM audio devices and find the one we want */
- for (wid=0; wid<widn; wid++) {
- if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {
- found = TRUE;
- break;
- }
- }
-
- if (found == FALSE) {
- WARN("No device found matching given ID!\n");
- return DSERR_NODRIVER;
- }
-
if (DSOUND_capture[wid]) {
WARN("already in use\n");
return DSERR_ALLOCATED;
diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c
index 5d4fb24..f59e566 100644
--- a/dlls/dsound/dsound_main.c
+++ b/dlls/dsound/dsound_main.c
@@ -50,17 +50,147 @@
#include "dsconf.h"
#include "ks.h"
#include "rpcproxy.h"
+#include "rpc.h"
+#include "rpcndr.h"
+#include "unknwn.h"
+#include "oleidl.h"
+#include "shobjidl.h"
+
#include "initguid.h"
#include "ksmedia.h"
#include "dsdriver.h"
+#include "propkey.h"
+#include "devpkey.h"
#include "dsound_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
+static IMMDeviceEnumerator *mme = NULL;
+
+static CALLBACK DWORD DSOUND_mmdevapi_thread(void *data)
+{
+ MSG msg;
+ HRESULT hr;
+ IMMDeviceEnumerator *mymme = NULL;
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+ hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mymme);
+ if (SUCCEEDED(hr))
+ mme = mymme;
+ SetEvent((HANDLE)data);
+ if (FAILED(hr))
+ {
+ ERR("Cannot use mmdevapi: %08x\n", hr);
+ goto out;
+ }
+ while (GetMessageW(&msg, NULL, 0, 0))
+ {
+ if (msg.hwnd)
+ {
+ DispatchMessageW(&msg);
+ continue;
+ }
+ ERR("Unknown message: %04x\n", msg.message);
+ }
+out:
+ if (mme)
+ IMMDeviceEnumerator_Release(mme);
+ mme = NULL;
+ CoUninitialize();
+ return 0;
+}
+
+static HANDLE DSOUND_mmdevapi_thread_handle;
+static DWORD DSOUND_mmdevapi_id;
+
+CRITICAL_SECTION mme_crst;
+static CRITICAL_SECTION_DEBUG mme_crst_debug =
+{
+ 0, 0, &mme_crst,
+ { &mme_crst_debug.ProcessLocksList,
+ &mme_crst_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": mme_crst_debug") }
+};
+CRITICAL_SECTION mme_crst = { &mme_crst_debug, -1, 0, 0, 0, 0 };
+
+IMMDeviceEnumerator *DSOUND_obtain_mme(void)
+{
+ EnterCriticalSection(&mme_crst);
+ if (!DSOUND_mmdevapi_id)
+ {
+ HANDLE ev = CreateEventW(0, 0, 0, 0);
+ DSOUND_mmdevapi_thread_handle = CreateThread(0, 0, DSOUND_mmdevapi_thread, ev, 0, &DSOUND_mmdevapi_id);
+ WaitForSingleObject(ev, INFINITE);
+ CloseHandle(ev);
+ }
+ LeaveCriticalSection(&mme_crst);
+ return mme;
+}
+
+HRESULT DSOUND_obtain_immdevice(EDataFlow flow, const GUID *guid, ERole role, IMMDevice **dev)
+{
+ IMMDeviceCollection *col;
+ HRESULT hr;
+ GUID curguid;
+ int i = 0;
+ if (!DSOUND_obtain_mme())
+ return DSERR_NODRIVER;
+ if (flow == eCapture && (IsEqualGUID(guid, &DSDEVID_DefaultVoiceCapture) ||
+ IsEqualGUID(guid, &DSDEVID_DefaultCapture)))
+ return IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, flow, role, dev);
+ if (flow == eRender && (IsEqualGUID(guid, &DSDEVID_DefaultVoicePlayback) ||
+ IsEqualGUID(guid, &DSDEVID_DefaultPlayback)))
+ return IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, flow, role, dev);
+ hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, flow, DEVICE_STATE_ACTIVE, &col);
+ if (FAILED(hr))
+ return E_NOTFOUND;
+ while (SUCCEEDED(IMMDeviceCollection_Item(col, i++, dev)))
+ {
+ hr = DSOUND_immdevice_getguid(*dev, &curguid);
+ if (SUCCEEDED(hr) && IsEqualGUID(&curguid, guid))
+ {
+ IMMDeviceCollection_Release(col);
+ return S_OK;
+ }
+ IMMDevice_Release(*dev);
+ }
+ IMMDeviceCollection_Release(col);
+ *dev = NULL;
+ return E_NOTFOUND;
+}
+
+HRESULT DSOUND_enumerate_immdevice(EDataFlow flow, IMMDeviceCollection **collection)
+{
+ if (!DSOUND_obtain_mme())
+ return DSERR_NODRIVER;
+ return IMMDeviceEnumerator_EnumAudioEndpoints(mme, flow, DEVICE_STATE_ACTIVE, collection);
+}
+
+HRESULT DSOUND_immdevice_getguid(IMMDevice *dev, GUID *guid)
+{
+ IPropertyStore *store;
+ PROPVARIANT pv = { VT_EMPTY };
+ HRESULT hr;
+ hr = IMMDevice_OpenPropertyStore(dev, STGM_READ, &store);
+ if (FAILED(hr))
+ return hr;
+ hr = IPropertyStore_GetValue(store, &PKEY_AudioEndpoint_GUID, &pv);
+ if (FAILED(hr))
+ {
+ IPropertyStore_Release(store);
+ return hr;
+ }
+ CLSIDFromString(pv.u.pwszVal, guid);
+ PropVariantClear(&pv);
+ IPropertyStore_Release(store);
+ return S_OK;
+}
+
DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS];
GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
-GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
+/* Some games keep a pointer to the guid instead of copying the guid itself, so keep a copy here */
+static GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
HRESULT mmErr(UINT err)
{
@@ -99,7 +229,6 @@ int ds_hw_accel = DS_HW_ACCEL_FULL;
int ds_default_sample_rate = 44100;
int ds_default_bits_per_sample = 16;
static int ds_default_playback;
-static int ds_default_capture;
static HINSTANCE instance;
/*
@@ -178,9 +307,6 @@ void setup_dsound_options(void)
if (!get_config_key( hkey, appkey, "MaxShadowSize", buffer, MAX_PATH ))
ds_snd_shadow_maxsize = atoi(buffer);
- if (!get_config_key( hkey, appkey, "DefaultCapture", buffer, MAX_PATH ))
- ds_default_capture = atoi(buffer);
-
if (!get_config_key( hkey, appkey, "DefaultSampleRate", buffer, MAX_PATH ))
ds_default_sample_rate = atoi(buffer);
@@ -201,7 +327,6 @@ void setup_dsound_options(void)
ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" :
"Unknown");
TRACE("ds_default_playback = %d\n", ds_default_playback);
- TRACE("ds_default_capture = %d\n", ds_default_playback);
TRACE("ds_default_sample_rate = %d\n", ds_default_sample_rate);
TRACE("ds_default_bits_per_sample = %d\n", ds_default_bits_per_sample);
TRACE("ds_snd_shadow_maxsize = %d\n", ds_snd_shadow_maxsize);
@@ -242,6 +367,7 @@ static const char * get_device_id(LPCGUID pGuid)
*/
HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
{
+ HRESULT hr;
TRACE("(%s,%p)\n", get_device_id(pGuidSrc),pGuidDest);
if ( pGuidSrc == NULL) {
@@ -262,10 +388,19 @@ HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
}
if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) ||
- IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
- *pGuidDest = DSOUND_capture_guids[ds_default_capture];
- TRACE("returns %s\n", get_device_id(pGuidDest));
- return DS_OK;
+ IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
+ ERole role = IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ? eCommunications : eMultimedia;
+ IMMDevice *dev = NULL;
+
+ hr = DSOUND_obtain_immdevice(eCapture, pGuidSrc, role, &dev);
+ if (SUCCEEDED(hr))
+ hr = DSOUND_immdevice_getguid(dev, pGuidDest);
+ if (dev)
+ IMMDevice_Release(dev);
+ if (FAILED(hr))
+ return DSERR_NODRIVER;
+ TRACE("returns %s\n", debugstr_guid(pGuidDest));
+ return DS_OK;
}
*pGuidDest = *pGuidSrc;
@@ -441,61 +576,54 @@ DirectSoundCaptureEnumerateW(
LPDSENUMCALLBACKW lpDSEnumCallback,
LPVOID lpContext)
{
- unsigned devs, wid;
- DSDRIVERDESC desc;
- GUID guid;
- int err;
- WCHAR wDesc[MAXPNAMELEN];
- WCHAR wName[MAXPNAMELEN];
+ HRESULT hr;
+ UINT devices = 0, i = 0;
+
+ WCHAR wDesc[MAXPNAMELEN] = { 'P','r','i','m','a','r','y',' ',
+ 'S','o','u','n','d',' ','C','a','p','t','u','r','e',' ','D','r','i','v','e','r',0 };
+ static const WCHAR wCapDrvName[] = { 'w','i','n','e','m','m','.','d','r','v', 0 };
+ static const WCHAR wEmptyDrv[] = { 0 };
+ IMMDevice *dev;
+ IPropertyStore *store;
+ IMMDeviceCollection *col;
+ PROPVARIANT pv = { VT_EMPTY };
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
if (lpDSEnumCallback == NULL) {
- WARN("invalid parameter: lpDSEnumCallback == NULL\n");
+ WARN("invalid parameter: lpDSEnumCallback == NULL\n");
return DSERR_INVALIDPARAM;
}
- devs = waveInGetNumDevs();
- if (devs > 0) {
- if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
- for (wid = 0; wid < devs; ++wid) {
- if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
- err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
- if (err == DS_OK) {
- TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
- "Primary Sound Capture Driver",desc.szDrvname,lpContext);
- MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
- wDesc, sizeof(wDesc)/sizeof(WCHAR) );
- MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
- wName, sizeof(wName)/sizeof(WCHAR) );
- wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
+ hr = DSOUND_enumerate_immdevice(eCapture, &col);
+ if (FAILED(hr))
+ return hr == DSERR_NODRIVER ? S_OK : hr;
- if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
- return DS_OK;
- }
- }
- }
- }
- }
+ if (FAILED(IMMDeviceCollection_GetCount(col, &devices)) || !devices)
+ goto done;
- for (wid = 0; wid < devs; ++wid) {
- err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
- if (err == DS_OK) {
- TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
- debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
- MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
- wDesc, sizeof(wDesc)/sizeof(WCHAR) );
- wDesc[(sizeof(wDesc)/sizeof(WCHAR)) - 1] = '\0';
+ if (lpDSEnumCallback(NULL, wDesc, wEmptyDrv, lpContext) == FALSE)
+ goto done;
- MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
- wName, sizeof(wName)/sizeof(WCHAR) );
- wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
-
- if (lpDSEnumCallback(&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE)
- return DS_OK;
- }
+ for (i = 0; i < devices; ++i)
+ {
+ IMMDeviceCollection_Item(col, i, &dev);
+ IMMDevice_OpenPropertyStore(dev, STGM_READ, &store);
+ IPropertyStore_GetValue(store, &PKEY_AudioEndpoint_GUID, &pv);
+ CLSIDFromString(pv.u.pwszVal, &DSOUND_capture_guids[i]);
+ PropVariantClear(&pv);
+ IPropertyStore_GetValue(store, (const PROPERTYKEY*) &DEVPKEY_Device_FriendlyName, &pv);
+ lstrcpynW(wDesc, pv.u.pwszVal, sizeof(wDesc)/sizeof(*wDesc));
+ PropVariantClear(&pv);
+ IPropertyStore_Release(store);
+ IMMDevice_Release(dev);
+
+ if (lpDSEnumCallback(&DSOUND_capture_guids[i], wDesc, wCapDrvName, lpContext) == FALSE)
+ break;
}
+done:
+ IMMDeviceCollection_Release(col);
return DS_OK;
}
@@ -672,9 +800,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
TRACE("DLL_PROCESS_ATTACH\n");
for (i = 0; i < MAXWAVEDRIVERS; i++) {
DSOUND_renderer[i] = NULL;
- DSOUND_capture[i] = NULL;
INIT_GUID(DSOUND_renderer_guids[i], 0xbd6dd71a, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
- INIT_GUID(DSOUND_capture_guids[i], 0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
}
instance = hInstDLL;
DisableThreadLibraryCalls(hInstDLL);
@@ -683,6 +809,11 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
break;
case DLL_PROCESS_DETACH:
TRACE("DLL_PROCESS_DETACH\n");
+ if (mme)
+ {
+ IMMDeviceEnumerator_Release(mme);
+ CloseHandle(DSOUND_mmdevapi_thread_handle);
+ }
break;
default:
TRACE("UNKNOWN REASON\n");
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index e5ef75c..df15c24 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -23,6 +23,10 @@
#define DS_TIME_RES 2 /* Resolution of multimedia timer */
#define DS_TIME_DEL 10 /* Delay of multimedia timer callback, and duration of HEL fragment */
+#include "wingdi.h"
+#include "mmdeviceapi.h"
+#include "audioclient.h"
+
#include "wine/list.h"
/* direct sound hardware acceleration levels */
@@ -403,9 +407,11 @@ HRESULT DSOUND_CaptureCreate8(REFIID riid, LPDIRECTSOUNDCAPTURE8 *ppDSC8);
extern DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS];
extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
-extern DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS];
-extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
-
HRESULT mmErr(UINT err);
void setup_dsound_options(void);
const char * dumpCooperativeLevel(DWORD level);
+
+HRESULT DSOUND_obtain_immdevice(EDataFlow flow, const GUID *guid, ERole role, IMMDevice **dev);
+HRESULT DSOUND_enumerate_immdevice(EDataFlow flow, IMMDeviceCollection **collection);
+HRESULT DSOUND_immdevice_getguid(IMMDevice *dev, GUID *guid);
+IMMDeviceEnumerator *DSOUND_obtain_mme(void);
diff --git a/dlls/dsound/propset.c b/dlls/dsound/propset.c
index f6c8091..cd1800e 100644
--- a/dlls/dsound/propset.c
+++ b/dlls/dsound/propset.c
@@ -136,17 +136,19 @@ static HRESULT DSPROPERTY_WaveDeviceMappingW(
}
}
} else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
- ULONG wid;
- unsigned int widn;
+ DWORD_PTR len;
+ WCHAR *data;
+ MMRESULT res;
+ ULONG wid, widn;
+ IMMDevice *dev = NULL;
TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
+
widn = waveInGetNumDevs();
for (wid = 0; wid < widn; wid++) {
WAVEINCAPSW capsW;
- MMRESULT res;
res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW));
if (res == MMSYSERR_NOERROR) {
if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
- ppd->DeviceId = DSOUND_capture_guids[wid];
hr = DS_OK;
TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
debugstr_w(ppd->DeviceName));
@@ -154,8 +156,26 @@ static HRESULT DSPROPERTY_WaveDeviceMappingW(
}
}
}
+ res = waveInMessage(UlongToHandle(wid),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len,0);
+ if (res == MMSYSERR_NOTSUPPORTED)
+ {
+ FIXME("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
+ ppd->DeviceId = DSDEVID_DefaultCapture;
+ goto out;
+ }
+ data = HeapAlloc(GetProcessHeap(), 0, len);
+ if (!data)
+ hr = E_OUTOFMEMORY;
+ else
+ waveInMessage(UlongToHandle(wid),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)data, len);
+ if (SUCCEEDED(hr))
+ hr = IMMDeviceEnumerator_GetDevice(DSOUND_obtain_mme(), data, &dev);
+ if (SUCCEEDED(hr))
+ hr = DSOUND_immdevice_getguid(dev, &ppd->DeviceId);
+ HeapFree(GetProcessHeap(), 0, data);
}
+out:
if (pcbReturned)
*pcbReturned = cbPropData;
@@ -207,6 +227,7 @@ static HRESULT DSPROPERTY_DescriptionW(
GUID dev_guid;
ULONG wod, wid, wodn, widn;
DSDRIVERDESC desc;
+ HRESULT hr;
TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
pPropData,cbPropData,pcbReturned);
@@ -237,22 +258,89 @@ static HRESULT DSPROPERTY_DescriptionW(
ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
ppd->WaveDeviceId = wod;
}
- else if (!memcmp(&dev_guid, &DSOUND_capture_guids[0], sizeof(GUID)-1)
- && wid < widn)
- {
- ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
- ppd->WaveDeviceId = wid;
- }
else
{
- WARN("Device not found\n");
- return E_PROP_ID_UNSUPPORTED;
+ IMMDeviceCollection *col = NULL;
+ IMMDevice *dev;
+ IMMEndpoint *endpoint = 0;
+ MMRESULT res;
+ EDataFlow flow;
+ WCHAR *str, *str2;
+ DWORD len = 0, len2;
+ GUID guid;
+ int i = 0;
+ static int once;
+
+ hr = DSOUND_enumerate_immdevice(eAll, &col);
+ if (FAILED(hr))
+ return hr;
+ while (IMMDeviceCollection_Item(col, i++, &dev) == S_OK)
+ {
+ DSOUND_immdevice_getguid(dev, &guid);
+ if (IsEqualGUID(&guid, &dev_guid))
+ break;
+ IMMDevice_Release(dev);
+ dev = NULL;
+ }
+ IMMDeviceCollection_Release(col);
+ if (!dev)
+ return E_PROP_ID_UNSUPPORTED;
+ IUnknown_QueryInterface(dev, &IID_IMMEndpoint, (void**)&endpoint);
+ IMMEndpoint_GetDataFlow(endpoint, &flow);
+ IUnknown_Release(endpoint);
+ ppd->DataFlow = flow == eCapture ? DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE : DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
+ IMMDevice_GetId(dev, &str);
+ IMMDevice_Release(dev);
+ len = (lstrlenW(str) + 1)*sizeof(WCHAR);
+ str2 = HeapAlloc(GetProcessHeap(), 0, len);
+
+ if (flow == eCapture)
+ {
+ for (i = 0; i < widn; ++i)
+ {
+ res = waveInMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len2,0);
+ if (res != MMSYSERR_NOERROR || len2 != len)
+ continue;
+ waveInMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)str2, len2);
+ if (!lstrcmpW(str2, str))
+ break;
+ }
+ if (i == widn)
+ {
+ if (!once++)
+ FIXME("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
+ else
+ TRACE("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
+ i = 0;
+ }
+ } else {
+ for (i = 0; i < wodn; ++i)
+ {
+ res = waveOutMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len2,0);
+ if (res != MMSYSERR_NOERROR || len2 != len)
+ continue;
+ waveOutMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)str2, len2);
+ if (!lstrcmpW(str2, str))
+ break;
+ }
+ if (i == wodn)
+ {
+ if (!once++)
+ FIXME("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
+ else
+ TRACE("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
+ i = 0;
+ }
+ }
+ ppd->WaveDeviceId = i;
+ HeapFree(GetProcessHeap(), 0, str);
+ CoTaskMemFree(str2);
}
if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER)
- err = waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0);
+ err = waveOutMessage(UlongToHandle(ppd->WaveDeviceId),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0);
else
- err = waveInMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0);
+ err = waveInMessage(UlongToHandle(ppd->WaveDeviceId),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0);
if (err != MMSYSERR_NOERROR)
{
@@ -293,6 +381,19 @@ static HRESULT DSPROPERTY_DescriptionW(
return S_OK;
}
+static BOOL CALLBACK enumerate_callback(GUID *guid, const WCHAR *desc, const WCHAR *module, void *ctx)
+{
+ PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = ctx;
+ DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
+
+ if (!guid)
+ return 1;
+
+ data.DeviceId = *guid;
+ DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
+ return ppd->Callback(&data, ppd->Context);
+}
+
static HRESULT DSPROPERTY_EnumerateW(
LPVOID pPropData,
ULONG cbPropData,
@@ -301,7 +402,7 @@ static HRESULT DSPROPERTY_EnumerateW(
PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData;
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
BOOL ret;
- int widn, wodn, i;
+ int wodn, i;
TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
pPropData,cbPropData,pcbReturned);
@@ -315,7 +416,6 @@ static HRESULT DSPROPERTY_EnumerateW(
}
wodn = waveOutGetNumDevs();
- widn = waveInGetNumDevs();
data.DeviceId = DSOUND_renderer_guids[0];
for (i = 0; i < wodn; ++i)
@@ -335,23 +435,7 @@ static HRESULT DSPROPERTY_EnumerateW(
return S_OK;
}
- data.DeviceId = DSOUND_capture_guids[0];
- for (i = 0; i < widn; ++i)
- {
- HRESULT hr;
- data.DeviceId.Data4[7] = i;
- hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
- if (FAILED(hr))
- {
- ERR("DescriptionW failed!\n");
- return S_OK;
- }
- ret = ppd->Callback(&data, ppd->Context);
- HeapFree(GetProcessHeap(), 0, data.Module);
- HeapFree(GetProcessHeap(), 0, data.Description);
- if (!ret)
- return S_OK;
- }
+ DirectSoundCaptureEnumerateW(enumerate_callback, ppd);
return S_OK;
}
--
1.7.4.1
--------------020006010500000201040707--
More information about the wine-patches
mailing list