Evilly merge tag 'wine-1.5.11' into dsoal
[wine/multimedia.git] / dlls / dsound / dsp / 0010_dsound:_Use_mmdevice_apis_for_enumerating_capture_devices.patch
bloba6ccb0f18e7d7916be6448dd5705261e5542d47d
1 commit 96c65dc2f2885f2548cf50f5912bd9ca6d9189c0
2 Author: Maarten Lankhorst <m.b.lankhorst@gmail.com>
3 Date: Fri Apr 8 02:03:28 2011 +0200
5 dsound: Use mmdevice apis for enumerating capture devices
7 diff --git a/dlls/dsound/Makefile.in b/dlls/dsound/Makefile.in
8 index 58b1998..8258637 100644
9 --- a/dlls/dsound/Makefile.in
10 +++ b/dlls/dsound/Makefile.in
11 @@ -1,6 +1,6 @@
12 MODULE = dsound.dll
13 IMPORTLIB = dsound
14 -IMPORTS = dxguid uuid winmm ole32 advapi32
15 +IMPORTS = dxguid uuid winmm ole32 advapi32 user32
17 C_SRCS = \
18 buffer.c \
19 diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c
20 index 174355a..6e6456b 100644
21 --- a/dlls/dsound/capture.c
22 +++ b/dlls/dsound/capture.c
23 @@ -1038,8 +1038,7 @@ static HRESULT DirectSoundCaptureDevice_Initialize(
24 LPCGUID lpcGUID)
26 HRESULT err = DSERR_INVALIDPARAM;
27 - unsigned wid, widn;
28 - BOOLEAN found = FALSE;
29 + unsigned wid = 0, widn;
30 GUID devGUID;
31 DirectSoundCaptureDevice *device = *ppDevice;
32 TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
33 @@ -1060,18 +1059,6 @@ static HRESULT DirectSoundCaptureDevice_Initialize(
36 /* enumerate WINMM audio devices and find the one we want */
37 - for (wid=0; wid<widn; wid++) {
38 - if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {
39 - found = TRUE;
40 - break;
41 - }
42 - }
44 - if (found == FALSE) {
45 - WARN("No device found matching given ID!\n");
46 - return DSERR_NODRIVER;
47 - }
49 if (DSOUND_capture[wid]) {
50 WARN("already in use\n");
51 return DSERR_ALLOCATED;
52 diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c
53 index 81dd7dd..1ee8a8f 100644
54 --- a/dlls/dsound/dsound_main.c
55 +++ b/dlls/dsound/dsound_main.c
56 @@ -50,17 +50,147 @@
57 #include "dsconf.h"
58 #include "ks.h"
59 #include "rpcproxy.h"
60 +#include "rpc.h"
61 +#include "rpcndr.h"
62 +#include "unknwn.h"
63 +#include "oleidl.h"
64 +#include "shobjidl.h"
66 #include "initguid.h"
67 #include "ksmedia.h"
68 #include "dsdriver.h"
69 +#include "propkey.h"
70 +#include "devpkey.h"
72 #include "dsound_private.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
76 +static IMMDeviceEnumerator *mme = NULL;
78 +static CALLBACK DWORD DSOUND_mmdevapi_thread(void *data)
80 + MSG msg;
81 + HRESULT hr;
82 + IMMDeviceEnumerator *mymme = NULL;
83 + CoInitializeEx(NULL, COINIT_MULTITHREADED);
84 + PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
85 + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mymme);
86 + if (SUCCEEDED(hr))
87 + mme = mymme;
88 + SetEvent((HANDLE)data);
89 + if (FAILED(hr))
90 + {
91 + ERR("Cannot use mmdevapi: %08x\n", hr);
92 + goto out;
93 + }
94 + while (GetMessageW(&msg, NULL, 0, 0))
95 + {
96 + if (msg.hwnd)
97 + {
98 + DispatchMessageW(&msg);
99 + continue;
101 + ERR("Unknown message: %04x\n", msg.message);
103 +out:
104 + if (mme)
105 + IMMDeviceEnumerator_Release(mme);
106 + mme = NULL;
107 + CoUninitialize();
108 + return 0;
111 +static HANDLE DSOUND_mmdevapi_thread_handle;
112 +static DWORD DSOUND_mmdevapi_id;
114 +CRITICAL_SECTION mme_crst;
115 +static CRITICAL_SECTION_DEBUG mme_crst_debug =
117 + 0, 0, &mme_crst,
118 + { &mme_crst_debug.ProcessLocksList,
119 + &mme_crst_debug.ProcessLocksList },
120 + 0, 0, { (DWORD_PTR)(__FILE__ ": mme_crst_debug") }
122 +CRITICAL_SECTION mme_crst = { &mme_crst_debug, -1, 0, 0, 0, 0 };
124 +IMMDeviceEnumerator *DSOUND_obtain_mme(void)
126 + EnterCriticalSection(&mme_crst);
127 + if (!DSOUND_mmdevapi_id)
129 + HANDLE ev = CreateEventW(0, 0, 0, 0);
130 + DSOUND_mmdevapi_thread_handle = CreateThread(0, 0, DSOUND_mmdevapi_thread, ev, 0, &DSOUND_mmdevapi_id);
131 + WaitForSingleObject(ev, INFINITE);
132 + CloseHandle(ev);
134 + LeaveCriticalSection(&mme_crst);
135 + return mme;
138 +HRESULT DSOUND_obtain_immdevice(EDataFlow flow, const GUID *guid, ERole role, IMMDevice **dev)
140 + IMMDeviceCollection *col;
141 + HRESULT hr;
142 + GUID curguid;
143 + int i = 0;
144 + if (!DSOUND_obtain_mme())
145 + return DSERR_NODRIVER;
146 + if (flow == eCapture && (IsEqualGUID(guid, &DSDEVID_DefaultVoiceCapture) ||
147 + IsEqualGUID(guid, &DSDEVID_DefaultCapture)))
148 + return IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, flow, role, dev);
149 + if (flow == eRender && (IsEqualGUID(guid, &DSDEVID_DefaultVoicePlayback) ||
150 + IsEqualGUID(guid, &DSDEVID_DefaultPlayback)))
151 + return IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, flow, role, dev);
152 + hr = IMMDeviceEnumerator_EnumAudioEndpoints(mme, flow, DEVICE_STATE_ACTIVE, &col);
153 + if (FAILED(hr))
154 + return E_NOTFOUND;
155 + while (SUCCEEDED(IMMDeviceCollection_Item(col, i++, dev)))
157 + hr = DSOUND_immdevice_getguid(*dev, &curguid);
158 + if (SUCCEEDED(hr) && IsEqualGUID(&curguid, guid))
160 + IMMDeviceCollection_Release(col);
161 + return S_OK;
163 + IMMDevice_Release(*dev);
165 + IMMDeviceCollection_Release(col);
166 + *dev = NULL;
167 + return E_NOTFOUND;
170 +HRESULT DSOUND_enumerate_immdevice(EDataFlow flow, IMMDeviceCollection **collection)
172 + if (!DSOUND_obtain_mme())
173 + return DSERR_NODRIVER;
174 + return IMMDeviceEnumerator_EnumAudioEndpoints(mme, flow, DEVICE_STATE_ACTIVE, collection);
177 +HRESULT DSOUND_immdevice_getguid(IMMDevice *dev, GUID *guid)
179 + IPropertyStore *store;
180 + PROPVARIANT pv = { VT_EMPTY };
181 + HRESULT hr;
182 + hr = IMMDevice_OpenPropertyStore(dev, STGM_READ, &store);
183 + if (FAILED(hr))
184 + return hr;
185 + hr = IPropertyStore_GetValue(store, &PKEY_AudioEndpoint_GUID, &pv);
186 + if (FAILED(hr))
188 + IPropertyStore_Release(store);
189 + return hr;
191 + CLSIDFromString(pv.u.pwszVal, guid);
192 + PropVariantClear(&pv);
193 + IPropertyStore_Release(store);
194 + return S_OK;
197 DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS];
198 GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
199 -GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
200 +/* Some games keep a pointer to the guid instead of copying the guid itself, so keep a copy here */
201 +static GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
203 HRESULT mmErr(UINT err)
205 @@ -99,7 +229,6 @@ int ds_hw_accel = DS_HW_ACCEL_FULL;
206 int ds_default_sample_rate = 44100;
207 int ds_default_bits_per_sample = 16;
208 static int ds_default_playback;
209 -static int ds_default_capture;
210 static HINSTANCE instance;
213 @@ -178,9 +307,6 @@ void setup_dsound_options(void)
214 if (!get_config_key( hkey, appkey, "MaxShadowSize", buffer, MAX_PATH ))
215 ds_snd_shadow_maxsize = atoi(buffer);
217 - if (!get_config_key( hkey, appkey, "DefaultCapture", buffer, MAX_PATH ))
218 - ds_default_capture = atoi(buffer);
220 if (!get_config_key( hkey, appkey, "DefaultSampleRate", buffer, MAX_PATH ))
221 ds_default_sample_rate = atoi(buffer);
223 @@ -201,7 +327,6 @@ void setup_dsound_options(void)
224 ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" :
225 "Unknown");
226 TRACE("ds_default_playback = %d\n", ds_default_playback);
227 - TRACE("ds_default_capture = %d\n", ds_default_playback);
228 TRACE("ds_default_sample_rate = %d\n", ds_default_sample_rate);
229 TRACE("ds_default_bits_per_sample = %d\n", ds_default_bits_per_sample);
230 TRACE("ds_snd_shadow_maxsize = %d\n", ds_snd_shadow_maxsize);
231 @@ -242,6 +367,7 @@ static const char * get_device_id(LPCGUID pGuid)
233 HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
235 + HRESULT hr;
236 TRACE("(%s,%p)\n", get_device_id(pGuidSrc),pGuidDest);
238 if ( pGuidSrc == NULL) {
239 @@ -262,10 +388,19 @@ HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
242 if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) ||
243 - IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
244 - *pGuidDest = DSOUND_capture_guids[ds_default_capture];
245 - TRACE("returns %s\n", get_device_id(pGuidDest));
246 - return DS_OK;
247 + IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
248 + ERole role = IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ? eCommunications : eMultimedia;
249 + IMMDevice *dev = NULL;
251 + hr = DSOUND_obtain_immdevice(eCapture, pGuidSrc, role, &dev);
252 + if (SUCCEEDED(hr))
253 + hr = DSOUND_immdevice_getguid(dev, pGuidDest);
254 + if (dev)
255 + IMMDevice_Release(dev);
256 + if (FAILED(hr))
257 + return DSERR_NODRIVER;
258 + TRACE("returns %s\n", debugstr_guid(pGuidDest));
259 + return DS_OK;
262 *pGuidDest = *pGuidSrc;
263 @@ -443,63 +578,54 @@ DirectSoundCaptureEnumerateW(
264 LPDSENUMCALLBACKW lpDSEnumCallback,
265 LPVOID lpContext)
267 - unsigned devs, wid;
268 - DSDRIVERDESC desc;
269 - GUID guid;
270 - int err;
271 - WCHAR wDesc[MAXPNAMELEN];
272 - WCHAR wName[MAXPNAMELEN];
273 + HRESULT hr;
274 + UINT devices = 0, i = 0;
276 + WCHAR wDesc[MAXPNAMELEN] = { 'P','r','i','m','a','r','y',' ',
277 + 'S','o','u','n','d',' ','C','a','p','t','u','r','e',' ','D','r','i','v','e','r',0 };
278 + static const WCHAR wCapDrvName[] = { 'w','i','n','e','m','m','.','d','r','v', 0 };
279 + static const WCHAR wEmptyDrv[] = { 0 };
280 + IMMDevice *dev;
281 + IPropertyStore *store;
282 + IMMDeviceCollection *col;
283 + PROPVARIANT pv = { VT_EMPTY };
285 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
287 if (lpDSEnumCallback == NULL) {
288 - WARN("invalid parameter: lpDSEnumCallback == NULL\n");
289 + WARN("invalid parameter: lpDSEnumCallback == NULL\n");
290 return DSERR_INVALIDPARAM;
293 - setup_dsound_options();
295 - devs = waveInGetNumDevs();
296 - if (devs > 0) {
297 - if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
298 - for (wid = 0; wid < devs; ++wid) {
299 - if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
300 - err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
301 - if (err == DS_OK) {
302 - TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
303 - "Primary Sound Capture Driver",desc.szDrvname,lpContext);
304 - MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
305 - wDesc, sizeof(wDesc)/sizeof(WCHAR) );
306 - MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
307 - wName, sizeof(wName)/sizeof(WCHAR) );
308 - wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
310 - if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
311 - return DS_OK;
317 + hr = DSOUND_enumerate_immdevice(eCapture, &col);
318 + if (FAILED(hr))
319 + return hr == DSERR_NODRIVER ? S_OK : hr;
321 - for (wid = 0; wid < devs; ++wid) {
322 - err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
323 - if (err == DS_OK) {
324 - TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
325 - debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
326 - MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
327 - wDesc, sizeof(wDesc)/sizeof(WCHAR) );
328 - wDesc[(sizeof(wDesc)/sizeof(WCHAR)) - 1] = '\0';
329 + if (FAILED(IMMDeviceCollection_GetCount(col, &devices)) || !devices)
330 + goto done;
332 - MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
333 - wName, sizeof(wName)/sizeof(WCHAR) );
334 - wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
335 + if (lpDSEnumCallback(NULL, wDesc, wEmptyDrv, lpContext) == FALSE)
336 + goto done;
338 - if (lpDSEnumCallback(&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE)
339 - return DS_OK;
341 + for (i = 0; i < devices; ++i)
343 + IMMDeviceCollection_Item(col, i, &dev);
344 + IMMDevice_OpenPropertyStore(dev, STGM_READ, &store);
345 + IPropertyStore_GetValue(store, &PKEY_AudioEndpoint_GUID, &pv);
346 + CLSIDFromString(pv.u.pwszVal, &DSOUND_capture_guids[i]);
347 + PropVariantClear(&pv);
348 + IPropertyStore_GetValue(store, (const PROPERTYKEY*) &DEVPKEY_Device_FriendlyName, &pv);
349 + lstrcpynW(wDesc, pv.u.pwszVal, sizeof(wDesc)/sizeof(*wDesc));
350 + PropVariantClear(&pv);
351 + IPropertyStore_Release(store);
352 + IMMDevice_Release(dev);
354 + if (lpDSEnumCallback(&DSOUND_capture_guids[i], wDesc, wCapDrvName, lpContext) == FALSE)
355 + break;
358 +done:
359 + IMMDeviceCollection_Release(col);
360 return DS_OK;
363 @@ -676,9 +802,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
364 TRACE("DLL_PROCESS_ATTACH\n");
365 for (i = 0; i < MAXWAVEDRIVERS; i++) {
366 DSOUND_renderer[i] = NULL;
367 - DSOUND_capture[i] = NULL;
368 INIT_GUID(DSOUND_renderer_guids[i], 0xbd6dd71a, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
369 - INIT_GUID(DSOUND_capture_guids[i], 0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
371 instance = hInstDLL;
372 DisableThreadLibraryCalls(hInstDLL);
373 @@ -687,6 +811,11 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
374 break;
375 case DLL_PROCESS_DETACH:
376 TRACE("DLL_PROCESS_DETACH\n");
377 + if (mme)
379 + IMMDeviceEnumerator_Release(mme);
380 + CloseHandle(DSOUND_mmdevapi_thread_handle);
382 break;
383 default:
384 TRACE("UNKNOWN REASON\n");
385 diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
386 index 1410a9c..1270fed 100644
387 --- a/dlls/dsound/dsound_private.h
388 +++ b/dlls/dsound/dsound_private.h
389 @@ -23,6 +23,10 @@
390 #define DS_TIME_RES 2 /* Resolution of multimedia timer */
391 #define DS_TIME_DEL 10 /* Delay of multimedia timer callback, and duration of HEL fragment */
393 +#include "wingdi.h"
394 +#include "mmdeviceapi.h"
395 +#include "audioclient.h"
397 #include "wine/list.h"
399 /* direct sound hardware acceleration levels */
400 @@ -387,9 +391,11 @@ HRESULT DSOUND_CaptureCreate8(REFIID riid, LPDIRECTSOUNDCAPTURE8 *ppDSC8) DECLSP
401 extern DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
402 extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
404 -extern DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
405 -extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
407 HRESULT mmErr(UINT err) DECLSPEC_HIDDEN;
408 void setup_dsound_options(void) DECLSPEC_HIDDEN;
409 const char * dumpCooperativeLevel(DWORD level) DECLSPEC_HIDDEN;
411 +HRESULT DSOUND_obtain_immdevice(EDataFlow flow, const GUID *guid, ERole role, IMMDevice **dev) DECLSPEC_HIDDEN;
412 +HRESULT DSOUND_enumerate_immdevice(EDataFlow flow, IMMDeviceCollection **collection) DECLSPEC_HIDDEN;
413 +HRESULT DSOUND_immdevice_getguid(IMMDevice *dev, GUID *guid) DECLSPEC_HIDDEN;
414 +IMMDeviceEnumerator *DSOUND_obtain_mme(void) DECLSPEC_HIDDEN;
415 diff --git a/dlls/dsound/propset.c b/dlls/dsound/propset.c
416 index e2d0e20..cf52bda 100644
417 --- a/dlls/dsound/propset.c
418 +++ b/dlls/dsound/propset.c
419 @@ -136,17 +136,19 @@ static HRESULT DSPROPERTY_WaveDeviceMappingW(
422 } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
423 - ULONG wid;
424 - unsigned int widn;
425 + DWORD_PTR len;
426 + WCHAR *data;
427 + MMRESULT res;
428 + ULONG wid, widn;
429 + IMMDevice *dev = NULL;
430 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
432 widn = waveInGetNumDevs();
433 for (wid = 0; wid < widn; wid++) {
434 WAVEINCAPSW capsW;
435 - MMRESULT res;
436 res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW));
437 if (res == MMSYSERR_NOERROR) {
438 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
439 - ppd->DeviceId = DSOUND_capture_guids[wid];
440 hr = DS_OK;
441 TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
442 debugstr_w(ppd->DeviceName));
443 @@ -154,8 +156,26 @@ static HRESULT DSPROPERTY_WaveDeviceMappingW(
447 + res = waveInMessage(UlongToHandle(wid),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len,0);
448 + if (res == MMSYSERR_NOTSUPPORTED)
450 + FIXME("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
451 + ppd->DeviceId = DSDEVID_DefaultCapture;
452 + goto out;
454 + data = HeapAlloc(GetProcessHeap(), 0, len);
455 + if (!data)
456 + hr = E_OUTOFMEMORY;
457 + else
458 + waveInMessage(UlongToHandle(wid),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)data, len);
459 + if (SUCCEEDED(hr))
460 + hr = IMMDeviceEnumerator_GetDevice(DSOUND_obtain_mme(), data, &dev);
461 + if (SUCCEEDED(hr))
462 + hr = DSOUND_immdevice_getguid(dev, &ppd->DeviceId);
463 + HeapFree(GetProcessHeap(), 0, data);
466 +out:
467 if (pcbReturned)
468 *pcbReturned = cbPropData;
470 @@ -207,6 +227,7 @@ static HRESULT DSPROPERTY_DescriptionW(
471 GUID dev_guid;
472 ULONG wod, wid, wodn, widn;
473 DSDRIVERDESC desc;
474 + HRESULT hr;
476 TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
477 pPropData,cbPropData,pcbReturned);
478 @@ -239,22 +260,89 @@ static HRESULT DSPROPERTY_DescriptionW(
479 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
480 ppd->WaveDeviceId = wod;
482 - else if (!memcmp(&dev_guid, &DSOUND_capture_guids[0], sizeof(GUID)-1)
483 - && wid < widn)
485 - ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
486 - ppd->WaveDeviceId = wid;
488 else
490 - WARN("Device not found\n");
491 - return E_PROP_ID_UNSUPPORTED;
492 + IMMDeviceCollection *col = NULL;
493 + IMMDevice *dev;
494 + IMMEndpoint *endpoint = 0;
495 + MMRESULT res;
496 + EDataFlow flow;
497 + WCHAR *str, *str2;
498 + DWORD len = 0, len2;
499 + GUID guid;
500 + int i = 0;
501 + static int once;
503 + hr = DSOUND_enumerate_immdevice(eAll, &col);
504 + if (FAILED(hr))
505 + return hr;
506 + while (IMMDeviceCollection_Item(col, i++, &dev) == S_OK)
508 + DSOUND_immdevice_getguid(dev, &guid);
509 + if (IsEqualGUID(&guid, &dev_guid))
510 + break;
511 + IMMDevice_Release(dev);
512 + dev = NULL;
514 + IMMDeviceCollection_Release(col);
515 + if (!dev)
516 + return E_PROP_ID_UNSUPPORTED;
517 + IUnknown_QueryInterface(dev, &IID_IMMEndpoint, (void**)&endpoint);
518 + IMMEndpoint_GetDataFlow(endpoint, &flow);
519 + IUnknown_Release(endpoint);
520 + ppd->DataFlow = flow == eCapture ? DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE : DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
521 + IMMDevice_GetId(dev, &str);
522 + IMMDevice_Release(dev);
523 + len = (lstrlenW(str) + 1)*sizeof(WCHAR);
524 + str2 = HeapAlloc(GetProcessHeap(), 0, len);
526 + if (flow == eCapture)
528 + for (i = 0; i < widn; ++i)
530 + res = waveInMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len2,0);
531 + if (res != MMSYSERR_NOERROR || len2 != len)
532 + continue;
533 + waveInMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)str2, len2);
534 + if (!lstrcmpW(str2, str))
535 + break;
537 + if (i == widn)
539 + if (!once++)
540 + FIXME("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
541 + else
542 + TRACE("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
543 + i = 0;
545 + } else {
546 + for (i = 0; i < wodn; ++i)
548 + res = waveOutMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEIDSIZE,(DWORD_PTR)&len2,0);
549 + if (res != MMSYSERR_NOERROR || len2 != len)
550 + continue;
551 + waveOutMessage(UlongToHandle(i),DRV_QUERYFUNCTIONINSTANCEID,(DWORD_PTR)str2, len2);
552 + if (!lstrcmpW(str2, str))
553 + break;
555 + if (i == wodn)
557 + if (!once++)
558 + FIXME("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
559 + else
560 + TRACE("No matching winmm device found, assuming winmm doesn't support mmdevapi and falling back to first device\n");
561 + i = 0;
564 + ppd->WaveDeviceId = i;
565 + HeapFree(GetProcessHeap(), 0, str);
566 + CoTaskMemFree(str2);
569 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER)
570 - err = waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel);
571 + err = waveOutMessage(UlongToHandle(ppd->WaveDeviceId),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0);
572 else
573 - err = waveInMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel);
574 + err = waveInMessage(UlongToHandle(ppd->WaveDeviceId),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0);
576 if (err != MMSYSERR_NOERROR)
578 @@ -295,6 +383,19 @@ static HRESULT DSPROPERTY_DescriptionW(
579 return S_OK;
582 +static BOOL CALLBACK enumerate_callback(GUID *guid, const WCHAR *desc, const WCHAR *module, void *ctx)
584 + PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = ctx;
585 + DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
587 + if (!guid)
588 + return 1;
590 + data.DeviceId = *guid;
591 + DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
592 + return ppd->Callback(&data, ppd->Context);
595 static HRESULT DSPROPERTY_EnumerateW(
596 LPVOID pPropData,
597 ULONG cbPropData,
598 @@ -303,7 +404,7 @@ static HRESULT DSPROPERTY_EnumerateW(
599 PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData;
600 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
601 BOOL ret;
602 - int widn, wodn, i;
603 + int wodn, i;
604 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
605 pPropData,cbPropData,pcbReturned);
607 @@ -317,7 +418,6 @@ static HRESULT DSPROPERTY_EnumerateW(
610 wodn = waveOutGetNumDevs();
611 - widn = waveInGetNumDevs();
613 data.DeviceId = DSOUND_renderer_guids[0];
614 for (i = 0; i < wodn; ++i)
615 @@ -337,23 +437,7 @@ static HRESULT DSPROPERTY_EnumerateW(
616 return S_OK;
619 - data.DeviceId = DSOUND_capture_guids[0];
620 - for (i = 0; i < widn; ++i)
622 - HRESULT hr;
623 - data.DeviceId.Data4[7] = i;
624 - hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
625 - if (FAILED(hr))
627 - ERR("DescriptionW failed!\n");
628 - return S_OK;
630 - ret = ppd->Callback(&data, ppd->Context);
631 - HeapFree(GetProcessHeap(), 0, data.Module);
632 - HeapFree(GetProcessHeap(), 0, data.Description);
633 - if (!ret)
634 - return S_OK;
636 + DirectSoundCaptureEnumerateW(enumerate_callback, ppd);
637 return S_OK;