1 /* DirectSound
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #define COBJMACROS
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "mmsystem.h"
29 #include "winternl.h"
30 #include "winnls.h"
31 #include "vfwmsgs.h"
32 #include "mmddk.h"
33 #include "wine/debug.h"
34 #include "dsound.h"
35 #include "dsdriver.h"
36 #include "dsound_private.h"
37 #include "dsconf.h"
38
39 #ifdef NONAMELESSSTRUCT
40 # define S(x) (x).s
41 #else
42 # define S(x) (x)
43 #endif
44
45 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
46
47
48 /*******************************************************************************
49 * IKsBufferPropertySet
50 */
51
52 /* IUnknown methods */
53 static HRESULT WINAPI IKsBufferPropertySetImpl_QueryInterface(
54 LPKSPROPERTYSET iface,
55 REFIID riid,
56 LPVOID *ppobj )
57 {
58 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
59 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
60
61 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
62 }
63
64 static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
65 {
66 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
67 ULONG ref = InterlockedIncrement(&(This->ref));
68 TRACE("(%p) ref was %d\n", This, ref - 1);
69 return ref;
70 }
71
72 static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
73 {
74 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
75 ULONG ref = InterlockedDecrement(&(This->ref));
76 TRACE("(%p) ref was %d\n", This, ref + 1);
77
78 if (!ref) {
79 This->dsb->iks = 0;
80 IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
81 HeapFree(GetProcessHeap(), 0, This);
82 TRACE("(%p) released\n", This);
83 }
84 return ref;
85 }
86
87 static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
88 LPKSPROPERTYSET iface,
89 REFGUID guidPropSet,
90 ULONG dwPropID,
91 LPVOID pInstanceData,
92 ULONG cbInstanceData,
93 LPVOID pPropData,
94 ULONG cbPropData,
95 PULONG pcbReturned )
96 {
97 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
98 PIDSDRIVERPROPERTYSET ps;
99 TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
100 This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
101
102 if (This->dsb->hwbuf) {
103 IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
104
105 if (ps) {
106 DSPROPERTY prop;
107 HRESULT hres;
108
109 S(prop).Set = *guidPropSet;
110 S(prop).Id = dwPropID;
111 S(prop).Flags = 0; /* unused */
112 S(prop).InstanceId = (ULONG)This->dsb->device;
113
114 hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
115
116 IDsDriverPropertySet_Release(ps);
117
118 return hres;
119 }
120 }
121
122 return E_PROP_ID_UNSUPPORTED;
123 }
124
125 static HRESULT WINAPI IKsBufferPropertySetImpl_Set(
126 LPKSPROPERTYSET iface,
127 REFGUID guidPropSet,
128 ULONG dwPropID,
129 LPVOID pInstanceData,
130 ULONG cbInstanceData,
131 LPVOID pPropData,
132 ULONG cbPropData )
133 {
134 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
135 PIDSDRIVERPROPERTYSET ps;
136 TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
137
138 if (This->dsb->hwbuf) {
139 IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
140
141 if (ps) {
142 DSPROPERTY prop;
143 HRESULT hres;
144
145 S(prop).Set = *guidPropSet;
146 S(prop).Id = dwPropID;
147 S(prop).Flags = 0; /* unused */
148 S(prop).InstanceId = (ULONG)This->dsb->device;
149 hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData);
150
151 IDsDriverPropertySet_Release(ps);
152
153 return hres;
154 }
155 }
156
157 return E_PROP_ID_UNSUPPORTED;
158 }
159
160 static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport(
161 LPKSPROPERTYSET iface,
162 REFGUID guidPropSet,
163 ULONG dwPropID,
164 PULONG pTypeSupport )
165 {
166 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
167 PIDSDRIVERPROPERTYSET ps;
168 TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
169
170 if (This->dsb->hwbuf) {
171 IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
172
173 if (ps) {
174 HRESULT hres;
175
176 hres = IDsDriverPropertySet_QuerySupport(ps,guidPropSet, dwPropID,pTypeSupport);
177
178 IDsDriverPropertySet_Release(ps);
179
180 return hres;
181 }
182 }
183
184 return E_PROP_ID_UNSUPPORTED;
185 }
186
187 static const IKsPropertySetVtbl iksbvt = {
188 IKsBufferPropertySetImpl_QueryInterface,
189 IKsBufferPropertySetImpl_AddRef,
190 IKsBufferPropertySetImpl_Release,
191 IKsBufferPropertySetImpl_Get,
192 IKsBufferPropertySetImpl_Set,
193 IKsBufferPropertySetImpl_QuerySupport
194 };
195
196 HRESULT IKsBufferPropertySetImpl_Create(
197 IDirectSoundBufferImpl *dsb,
198 IKsBufferPropertySetImpl **piks)
199 {
200 IKsBufferPropertySetImpl *iks;
201 TRACE("(%p,%p)\n",dsb,piks);
202 *piks = NULL;
203
204 iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
205 if (iks == 0) {
206 WARN("out of memory\n");
207 *piks = NULL;
208 return DSERR_OUTOFMEMORY;
209 }
210
211 iks->ref = 0;
212 iks->dsb = dsb;
213 dsb->iks = iks;
214 iks->lpVtbl = &iksbvt;
215
216 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
217
218 *piks = iks;
219 return S_OK;
220 }
221
222 HRESULT IKsBufferPropertySetImpl_Destroy(
223 IKsBufferPropertySetImpl *piks)
224 {
225 TRACE("(%p)\n",piks);
226
227 while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
228
229 return S_OK;
230 }
231
232 /*******************************************************************************
233 * IKsPrivatePropertySet
234 */
235
236 /* IUnknown methods */
237 static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface(
238 LPKSPROPERTYSET iface,
239 REFIID riid,
240 LPVOID *ppobj )
241 {
242 IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
243 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
244
245 if (IsEqualIID(riid, &IID_IUnknown) ||
246 IsEqualIID(riid, &IID_IKsPropertySet)) {
247 *ppobj = iface;
248 IUnknown_AddRef(iface);
249 return S_OK;
250 }
251 *ppobj = NULL;
252 return E_NOINTERFACE;
253 }
254
255 static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface)
256 {
257 IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
258 ULONG ref = InterlockedIncrement(&(This->ref));
259 TRACE("(%p) ref was %d\n", This, ref - 1);
260 return ref;
261 }
262
263 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
264 {
265 IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
266 ULONG ref = InterlockedDecrement(&(This->ref));
267 TRACE("(%p) ref was %d\n", This, ref + 1);
268
269 if (!ref) {
270 HeapFree(GetProcessHeap(), 0, This);
271 TRACE("(%p) released\n", This);
272 }
273 return ref;
274 }
275
276 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingA(
277 LPVOID pPropData,
278 ULONG cbPropData,
279 PULONG pcbReturned )
280 {
281 HRESULT hr = DSERR_INVALIDPARAM;
282 PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA ppd;
283 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
284 pPropData,cbPropData,pcbReturned);
285
286 ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA) pPropData;
287
288 if (!ppd) {
289 WARN("invalid parameter: pPropData\n");
290 return DSERR_INVALIDPARAM;
291 }
292
293 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
294 ULONG wod;
295 unsigned int wodn;
296 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
297 wodn = waveOutGetNumDevs();
298 for (wod = 0; wod < wodn; wod++) {
299 WAVEOUTCAPSA capsA;
300 MMRESULT res;
301 res = waveOutGetDevCapsA(wod, &capsA, sizeof(capsA));
302 if (res == MMSYSERR_NOERROR) {
303 if (lstrcmpA(capsA.szPname, ppd->DeviceName) == 0) {
304 ppd->DeviceId = DSOUND_renderer_guids[wod];
305 hr = DS_OK;
306 TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
307 ppd->DeviceName);
308 break;
309 }
310 }
311 }
312 } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
313 ULONG wid;
314 unsigned int widn;
315 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
316 widn = waveInGetNumDevs();
317 for (wid = 0; wid < widn; wid++) {
318 WAVEINCAPSA capsA;
319 MMRESULT res;
320 res = waveInGetDevCapsA(wid, &capsA, sizeof(capsA));
321 if (res == MMSYSERR_NOERROR) {
322 if (lstrcmpA(capsA.szPname, ppd->DeviceName) == 0) {
323 ppd->DeviceId = DSOUND_capture_guids[wid];
324 TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
325 ppd->DeviceName);
326 hr = DS_OK;
327 break;
328 }
329 }
330 }
331 }
332
333 if (pcbReturned)
334 *pcbReturned = cbPropData;
335
336 return hr;
337 }
338
339 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingW(
340 LPVOID pPropData,
341 ULONG cbPropData,
342 PULONG pcbReturned )
343 {
344 HRESULT hr = DSERR_INVALIDPARAM;
345 PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd;
346 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
347 pPropData,cbPropData,pcbReturned);
348
349 ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA) pPropData;
350
351 if (!ppd) {
352 WARN("invalid parameter: pPropData\n");
353 return DSERR_INVALIDPARAM;
354 }
355
356 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
357 ULONG wod;
358 unsigned int wodn;
359 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
360 wodn = waveOutGetNumDevs();
361 for (wod = 0; wod < wodn; wod++) {
362 WAVEOUTCAPSW capsW;
363 MMRESULT res;
364 res = waveOutGetDevCapsW(wod, &capsW, sizeof(capsW));
365 if (res == MMSYSERR_NOERROR) {
366 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
367 ppd->DeviceId = DSOUND_renderer_guids[wod];
368 hr = DS_OK;
369 TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
370 debugstr_w(ppd->DeviceName));
371 break;
372 }
373 }
374 }
375 } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
376 ULONG wid;
377 unsigned int widn;
378 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
379 widn = waveInGetNumDevs();
380 for (wid = 0; wid < widn; wid++) {
381 WAVEINCAPSW capsW;
382 MMRESULT res;
383 res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW));
384 if (res == MMSYSERR_NOERROR) {
385 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
386 ppd->DeviceId = DSOUND_capture_guids[wid];
387 hr = DS_OK;
388 TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
389 debugstr_w(ppd->DeviceName));
390 break;
391 }
392 }
393 }
394 }
395
396 if (pcbReturned)
397 *pcbReturned = cbPropData;
398
399 return hr;
400 }
401
402 static HRESULT WINAPI DSPROPERTY_Description1(
403 LPVOID pPropData,
404 ULONG cbPropData,
405 PULONG pcbReturned )
406 {
407 HRESULT err;
408 GUID guid, dev_guid;
409 PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA ppd;
410 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
411 pPropData,cbPropData,pcbReturned);
412
413 ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA) pPropData;
414
415 if (!ppd) {
416 WARN("invalid parameter: pPropData\n");
417 return DSERR_INVALIDPARAM;
418 }
419
420 TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
421 if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
422 /* default device of type specified by ppd->DataFlow */
423 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
424 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
425 } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
426 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
427 } else {
428 TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
429 }
430 FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n",
431 pPropData,cbPropData,pcbReturned);
432 return E_PROP_ID_UNSUPPORTED;
433 }
434
435 ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
436 GetDeviceID(&ppd->DeviceId, &dev_guid);
437
438 if ( IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultPlayback) ||
439 IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultVoicePlayback) ) {
440 ULONG wod;
441 unsigned int wodn;
442 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
443 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
444 wodn = waveOutGetNumDevs();
445 for (wod = 0; wod < wodn; wod++) {
446 if (IsEqualGUID( &dev_guid, &DSOUND_renderer_guids[wod] ) ) {
447 DSDRIVERDESC desc;
448 ppd->WaveDeviceId = wod;
449 ppd->Devnode = wod;
450 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
451 if (err == DS_OK) {
452 PIDSDRIVER drv = NULL;
453 lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA));
454 lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA));
455 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
456 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
457 err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
458 if (err == DS_OK && drv)
459 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
460 else
461 WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
462 break;
463 } else {
464 WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
465 return E_PROP_ID_UNSUPPORTED;
466 }
467 }
468 }
469 } else if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
470 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
471 ULONG wid;
472 unsigned int widn;
473 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
474 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
475 widn = waveInGetNumDevs();
476 for (wid = 0; wid < widn; wid++) {
477 if (IsEqualGUID( &dev_guid, &guid) ) {
478 DSDRIVERDESC desc;
479 ppd->WaveDeviceId = wid;
480 ppd->Devnode = wid;
481 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
482 if (err == DS_OK) {
483 PIDSCDRIVER drv;
484 lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA));
485 lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA));
486 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
487 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
488 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0));
489 if (err == DS_OK && drv)
490 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
491 else
492 WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
493 break;
494 } else {
495 WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
496 return E_PROP_ID_UNSUPPORTED;
497 }
498 }
499 }
500 } else {
501 BOOL found = FALSE;
502 ULONG wod;
503 unsigned int wodn;
504 /* given specific device so try the render devices first */
505 wodn = waveOutGetNumDevs();
506 for (wod = 0; wod < wodn; wod++) {
507 if (IsEqualGUID( &ppd->DeviceId, &DSOUND_renderer_guids[wod] ) ) {
508 DSDRIVERDESC desc;
509 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
510 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
511 ppd->WaveDeviceId = wod;
512 ppd->Devnode = wod;
513 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
514 if (err == DS_OK) {
515 PIDSDRIVER drv = NULL;
516 lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA));
517 lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA));
518 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
519 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
520 err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
521 if (err == DS_OK && drv)
522 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
523 else
524 WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
525 found = TRUE;
526 break;
527 } else {
528 WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
529 return E_PROP_ID_UNSUPPORTED;
530 }
531 }
532 }
533
534 if (found == FALSE) {
535 ULONG wid;
536 unsigned int widn;
537 /* given specific device so try the capture devices next */
538 widn = waveInGetNumDevs();
539 for (wid = 0; wid < widn; wid++) {
540 if (IsEqualGUID( &ppd->DeviceId, &DSOUND_capture_guids[wid] ) ) {
541 DSDRIVERDESC desc;
542 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
543 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
544 ppd->WaveDeviceId = wid;
545 ppd->Devnode = wid;
546 err = mmErr(waveInMessage((HWAVEIN)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
547 if (err == DS_OK) {
548 PIDSDRIVER drv = NULL;
549 lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA));
550 lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA));
551 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
552 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
553 err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
554 if (err == DS_OK && drv)
555 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
556 else
557 WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
558 found = TRUE;
559 break;
560 } else {
561 WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
562 return E_PROP_ID_UNSUPPORTED;
563 }
564 }
565 }
566
567 if (found == FALSE) {
568 WARN("device not found\n");
569 return E_PROP_ID_UNSUPPORTED;
570 }
571 }
572 }
573
574 if (pcbReturned) {
575 *pcbReturned = cbPropData;
576 TRACE("*pcbReturned=%d\n", *pcbReturned);
577 }
578
579 return S_OK;
580 }
581
582 static HRESULT WINAPI DSPROPERTY_DescriptionA(
583 LPVOID pPropData,
584 ULONG cbPropData,
585 PULONG pcbReturned )
586 {
587 PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA) pPropData;
588 HRESULT err;
589 GUID dev_guid;
590 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
591 pPropData,cbPropData,pcbReturned);
592
593 TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
594 if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
595 /* default device of type specified by ppd->DataFlow */
596 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
597 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
598 } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
599 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
600 } else {
601 TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
602 }
603 FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n",
604 pPropData,cbPropData,pcbReturned);
605 return E_PROP_ID_UNSUPPORTED;
606 }
607
608 ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
609 GetDeviceID(&ppd->DeviceId, &dev_guid);
610
611 if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
612 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
613 ULONG wod;
614 unsigned int wodn;
615 if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) )
616 TRACE("DSDEVID_DefaultPlayback\n");
617 else
618 TRACE("DSDEVID_DefaultVoicePlayback\n");
619 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
620 wodn = waveOutGetNumDevs();
621 for (wod = 0; wod < wodn; wod++) {
622 if (IsEqualGUID( &dev_guid, &DSOUND_renderer_guids[wod] ) ) {
623 DSDRIVERDESC desc;
624 ppd->WaveDeviceId = wod;
625 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
626 if (err == DS_OK) {
627 PIDSDRIVER drv = NULL;
628 /* FIXME: this is a memory leak */
629 CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
630 CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
631 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
632
633 if (szDescription && szModule && szInterface) {
634 strcpy(szDescription, desc.szDesc);
635 strcpy(szModule, desc.szDrvname);
636 strcpy(szInterface, "Interface");
637
638 ppd->Description = szDescription;
639 ppd->Module = szModule;
640 ppd->Interface = szInterface;
641 err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
642 if (err == DS_OK && drv)
643 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
644 else
645 WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
646 break;
647 } else {
648 WARN("no memory\n");
649 HeapFree(GetProcessHeap(), 0, szDescription);
650 HeapFree(GetProcessHeap(), 0, szModule);
651 HeapFree(GetProcessHeap(), 0, szInterface);
652 return E_OUTOFMEMORY;
653 }
654 } else {
655 WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
656 return E_PROP_ID_UNSUPPORTED;
657 }
658 }
659 }
660 } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
661 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
662 ULONG wid;
663 unsigned int widn;
664 if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) )
665 TRACE("DSDEVID_DefaultCapture\n");
666 else
667 TRACE("DSDEVID_DefaultVoiceCapture\n");
668 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
669 widn = waveInGetNumDevs();
670 for (wid = 0; wid < widn; wid++) {
671 if (IsEqualGUID( &dev_guid, &DSOUND_capture_guids[wid] ) ) {
672 DSDRIVERDESC desc;
673 ppd->WaveDeviceId = wid;
674 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
675 if (err == DS_OK) {
676 PIDSCDRIVER drv;
677 /* FIXME: this is a memory leak */
678 CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
679 CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
680 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
681
682 if (szDescription && szModule && szInterface) {
683 strcpy(szDescription, desc.szDesc);
684 strcpy(szModule, desc.szDrvname);
685 strcpy(szInterface, "Interface");
686
687 ppd->Description = szDescription;
688 ppd->Module = szModule;
689 ppd->Interface = szInterface;
690 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0));
691 if (err == DS_OK && drv)
692 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
693 else
694 WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
695 break;
696 } else {
697 WARN("no memory\n");
698 HeapFree(GetProcessHeap(), 0, szDescription);
699 HeapFree(GetProcessHeap(), 0, szModule);
700 HeapFree(GetProcessHeap(), 0, szInterface);
701 return E_OUTOFMEMORY;
702 }
703 } else {
704 WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
705 return E_PROP_ID_UNSUPPORTED;
706 }
707 }
708 }
709 } else {
710 BOOL found = FALSE;
711 ULONG wod;
712 unsigned int wodn;
713 /* given specific device so try the render devices first */
714 TRACE("Checking renderer devices\n");
715 wodn = waveOutGetNumDevs();
716 for (wod = 0; wod < wodn; wod++) {
717 if (IsEqualGUID( &ppd->DeviceId, &DSOUND_renderer_guids[wod] ) ) {
718 DSDRIVERDESC desc;
719 TRACE("DSOUND_renderer_guids[%d]\n", wod);
720 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
721 ppd->WaveDeviceId = wod;
722 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
723 if (err == DS_OK) {
724 PIDSDRIVER drv = NULL;
725 /* FIXME: this is a memory leak */
726 CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
727 CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
728 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
729
730 if (szDescription && szModule && szInterface) {
731 strcpy(szDescription, desc.szDesc);
732 strcpy(szModule, desc.szDrvname);
733 strcpy(szInterface, "Interface");
734
735 ppd->Description = szDescription;
736 ppd->Module = szModule;
737 ppd->Interface = szInterface;
738 err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0));
739 if (err == DS_OK && drv)
740 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
741 else
742 WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n");
743 found = TRUE;
744 break;
745 } else {
746 WARN("no memory\n");
747 HeapFree(GetProcessHeap(), 0, szDescription);
748 HeapFree(GetProcessHeap(), 0, szModule);
749 HeapFree(GetProcessHeap(), 0, szInterface);
750 return E_OUTOFMEMORY;
751 }
752 } else {
753 WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n");
754 return E_PROP_ID_UNSUPPORTED;
755 }
756 }
757 }
758
759 if (found == FALSE) {
760 ULONG wid;
761 unsigned int widn;
762 TRACE("Checking capture devices\n");
763 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
764 widn = waveInGetNumDevs();
765 for (wid = 0; wid < widn; wid++) {
766 if (IsEqualGUID( &ppd->DeviceId, &DSOUND_capture_guids[wid] ) ) {
767 DSDRIVERDESC desc;
768 TRACE("DSOUND_capture_guids[%d]\n", wid);
769 ppd->WaveDeviceId = wid;
770 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
771 if (err == DS_OK) {
772 PIDSCDRIVER drv;
773 /* FIXME: this is a memory leak */
774 CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
775 CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1);
776 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
777
778 if (szDescription && szModule && szInterface) {
779 strcpy(szDescription, desc.szDesc);
780 strcpy(szModule, desc.szDrvname);
781 strcpy(szInterface, "Interface");
782
783 ppd->Description = szDescription;
784 ppd->Module = szModule;
785 ppd->Interface = szInterface;
786 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0));
787 if (err == DS_OK && drv)
788 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
789 else
790 WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n");
791 found = TRUE;
792 break;
793 } else {
794 WARN("no memory\n");
795 HeapFree(GetProcessHeap(), 0, szDescription);
796 HeapFree(GetProcessHeap(), 0, szModule);
797 HeapFree(GetProcessHeap(), 0, szInterface);
798 return E_OUTOFMEMORY;
799 }
800 } else {
801 WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n");
802 return E_PROP_ID_UNSUPPORTED;
803 }
804 }
805 }
806 }
807
808 if (found == FALSE) {
809 WARN("device not found\n");
810 return E_PROP_ID_UNSUPPORTED;
811 }
812 }
813
814 if (pcbReturned) {
815 *pcbReturned = cbPropData;
816 TRACE("*pcbReturned=%d\n", *pcbReturned);
817 }
818
819 return S_OK;
820 }
821
822 static HRESULT WINAPI DSPROPERTY_DescriptionW(
823 LPVOID pPropData,
824 ULONG cbPropData,
825 PULONG pcbReturned )
826 {
827 PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA) pPropData;
828 HRESULT err;
829 GUID dev_guid;
830 TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
831 pPropData,cbPropData,pcbReturned);
832
833 TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
834 if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
835 /* default device of type specified by ppd->DataFlow */
836 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
837 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
838 } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
839 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
840 } else {
841 TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
842 }
843 FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n",
844 pPropData,cbPropData,pcbReturned);
845 return E_PROP_ID_UNSUPPORTED;
846 }
847
848 ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
849 GetDeviceID(&ppd->DeviceId, &dev_guid);
850
851 if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
852 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
853 ULONG wod;
854 unsigned int wodn;
855 if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) )
856 TRACE("DSDEVID_DefaultPlayback\n");
857 else
858 TRACE("DSDEVID_DefaultVoicePlayback\n");
859 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
860 wodn = waveOutGetNumDevs();
861 for (wod = 0; wod < wodn; wod++) {
862 if (IsEqualGUID( &dev_guid, &DSOUND_renderer_guids[wod] ) ) {
863 DSDRIVERDESC desc;
864 TRACE("DSOUND_renderer_guids[%d]\n", wod);
865 ppd->WaveDeviceId = wod;
866 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0));
867 if (err == DS_OK) {
868 PIDSDRIVER drv = NULL;
869 /* FIXME: this is a memory leak */
870 WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
871 WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
872 WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);