3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
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.
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.
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
23 #define NONAMELESSSTRUCT
24 #define NONAMELESSUNION
35 #include "wine/debug.h"
37 #include "dsound_private.h"
44 #ifdef NONAMELESSSTRUCT
50 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
52 static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 };
54 typedef struct IKsPrivatePropertySetImpl
56 IKsPropertySet IKsPropertySet_iface;
58 } IKsPrivatePropertySetImpl;
60 static IKsPrivatePropertySetImpl *impl_from_IKsPropertySet(IKsPropertySet *iface)
62 return CONTAINING_RECORD(iface, IKsPrivatePropertySetImpl, IKsPropertySet_iface);
65 /*******************************************************************************
66 * IKsPrivatePropertySet
69 /* IUnknown methods */
70 static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface(
71 IKsPropertySet *iface, REFIID riid, void **ppobj)
73 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
74 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
76 if (IsEqualIID(riid, &IID_IUnknown) ||
77 IsEqualIID(riid, &IID_IKsPropertySet)) {
79 IKsPropertySet_AddRef(iface);
86 static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface)
88 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
89 ULONG ref = InterlockedIncrement(&(This->ref));
90 TRACE("(%p) ref was %d\n", This, ref - 1);
94 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
96 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
97 ULONG ref = InterlockedDecrement(&(This->ref));
98 TRACE("(%p) ref was %d\n", This, ref + 1);
101 HeapFree(GetProcessHeap(), 0, This);
102 TRACE("(%p) released\n", This);
108 const WCHAR *tgt_name;
112 static BOOL CALLBACK search_callback(GUID *guid, const WCHAR *desc,
113 const WCHAR *module, void *user)
115 struct search_data *search = user;
117 if(!lstrcmpW(desc, search->tgt_name)){
118 *search->found_guid = *guid;
125 static HRESULT DSPROPERTY_WaveDeviceMappingW(
131 PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd = pPropData;
132 struct search_data search;
134 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
135 pPropData,cbPropData,pcbReturned);
138 WARN("invalid parameter: pPropData\n");
139 return DSERR_INVALIDPARAM;
142 search.tgt_name = ppd->DeviceName;
143 search.found_guid = &ppd->DeviceId;
145 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER)
146 hr = enumerate_mmdevices(eRender, DSOUND_renderer_guids,
147 search_callback, &search);
148 else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE)
149 hr = enumerate_mmdevices(eCapture, DSOUND_capture_guids,
150 search_callback, &search);
152 return DSERR_INVALIDPARAM;
155 /* device was not found */
156 return DSERR_INVALIDPARAM;
159 *pcbReturned = cbPropData;
164 static HRESULT DSPROPERTY_WaveDeviceMappingA(
169 DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA *ppd = pPropData;
170 DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA data;
174 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
175 pPropData,cbPropData,pcbReturned);
177 if (!ppd || !ppd->DeviceName) {
178 WARN("invalid parameter: ppd=%p\n", ppd);
179 return DSERR_INVALIDPARAM;
182 data.DataFlow = ppd->DataFlow;
183 len = MultiByteToWideChar(CP_ACP, 0, ppd->DeviceName, -1, NULL, 0);
184 data.DeviceName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
185 if (!data.DeviceName)
186 return E_OUTOFMEMORY;
187 MultiByteToWideChar(CP_ACP, 0, ppd->DeviceName, -1, data.DeviceName, len);
189 hr = DSPROPERTY_WaveDeviceMappingW(&data, cbPropData, pcbReturned);
190 HeapFree(GetProcessHeap(), 0, data.DeviceName);
191 ppd->DeviceId = data.DeviceId;
194 *pcbReturned = cbPropData;
199 static HRESULT DSPROPERTY_DescriptionW(
204 PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = pPropData;
212 TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
213 pPropData,cbPropData,pcbReturned);
215 TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
216 if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
217 /* default device of type specified by ppd->DataFlow */
218 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
219 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
220 ppd->DeviceId = DSDEVID_DefaultCapture;
221 } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
222 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
223 ppd->DeviceId = DSDEVID_DefaultPlayback;
225 WARN("DataFlow=Unknown(%d)\n", ppd->DataFlow);
226 return E_PROP_ID_UNSUPPORTED;
230 setup_dsound_options();
232 GetDeviceID(&ppd->DeviceId, &dev_guid);
234 hr = get_mmdevice(eRender, &dev_guid, &mmdevice);
236 hr = get_mmdevice(eCapture, &dev_guid, &mmdevice);
241 hr = IMMDevice_OpenPropertyStore(mmdevice, STGM_READ, &ps);
243 IMMDevice_Release(mmdevice);
244 WARN("OpenPropertyStore failed: %08x\n", hr);
248 hr = IPropertyStore_GetValue(ps,
249 (const PROPERTYKEY *)&DEVPKEY_Device_FriendlyName, &pv);
251 IPropertyStore_Release(ps);
252 IMMDevice_Release(mmdevice);
253 WARN("GetValue(FriendlyName) failed: %08x\n", hr);
257 desclen = lstrlenW(pv.u.pwszVal) + 1;
258 /* FIXME: Still a memory leak.. */
259 ppd->Description = HeapAlloc(GetProcessHeap(), 0, desclen * sizeof(WCHAR));
260 memcpy(ppd->Description, pv.u.pwszVal, desclen * sizeof(WCHAR));
261 ppd->Module = wine_vxd_drv;
262 ppd->Interface = wInterface;
263 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
265 PropVariantClear(&pv);
266 IPropertyStore_Release(ps);
267 IMMDevice_Release(mmdevice);
270 *pcbReturned = sizeof(*ppd);
271 TRACE("*pcbReturned=%d\n", *pcbReturned);
278 BOOL CALLBACK enum_callback(GUID *guid, const WCHAR *desc, const WCHAR *module,
281 PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = user;
282 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
286 TRACE("%s %s %s %p\n", wine_dbgstr_guid(guid), wine_dbgstr_w(desc),
287 wine_dbgstr_w(module), user);
292 data.DeviceId = *guid;
294 len = lstrlenW(module) + 1;
295 data.Module = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
296 memcpy(data.Module, module, len * sizeof(WCHAR));
298 len = lstrlenW(desc) + 1;
299 data.Description = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
300 memcpy(data.Description, desc, len * sizeof(WCHAR));
302 data.Interface = wInterface;
304 ret = ppd->Callback(&data, ppd->Context);
306 HeapFree(GetProcessHeap(), 0, data.Module);
307 HeapFree(GetProcessHeap(), 0, data.Description);
312 static HRESULT DSPROPERTY_EnumerateW(
317 PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData;
320 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
321 pPropData,cbPropData,pcbReturned);
326 if (!ppd || !ppd->Callback)
328 WARN("Invalid ppd %p\n", ppd);
329 return E_PROP_ID_UNSUPPORTED;
332 hr = enumerate_mmdevices(eRender, DSOUND_renderer_guids,
336 hr = enumerate_mmdevices(eCapture, DSOUND_capture_guids,
339 return SUCCEEDED(hr) ? DS_OK : hr;
342 static BOOL DSPROPERTY_descWtoA(const DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW,
343 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *dataA)
345 DWORD modlen, desclen;
346 static char Interface[] = "Interface";
348 modlen = WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, NULL, 0, NULL, NULL);
349 desclen = WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, NULL, 0, NULL, NULL);
350 dataA->Type = dataW->Type;
351 dataA->DataFlow = dataW->DataFlow;
352 dataA->DeviceId = dataW->DeviceId;
353 dataA->WaveDeviceId = dataW->WaveDeviceId;
354 dataA->Interface = Interface;
355 dataA->Module = HeapAlloc(GetProcessHeap(), 0, modlen);
356 dataA->Description = HeapAlloc(GetProcessHeap(), 0, desclen);
357 if (!dataA->Module || !dataA->Description)
359 HeapFree(GetProcessHeap(), 0, dataA->Module);
360 HeapFree(GetProcessHeap(), 0, dataA->Description);
361 dataA->Module = dataA->Description = NULL;
365 WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, dataA->Module, modlen, NULL, NULL);
366 WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, dataA->Description, desclen, NULL, NULL);
370 static void DSPROPERTY_descWto1(const DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW,
371 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA *data1)
373 data1->DeviceId = dataW->DeviceId;
374 lstrcpynW(data1->ModuleW, dataW->Module, sizeof(data1->ModuleW)/sizeof(*data1->ModuleW));
375 lstrcpynW(data1->DescriptionW, dataW->Description, sizeof(data1->DescriptionW)/sizeof(*data1->DescriptionW));
376 WideCharToMultiByte(CP_ACP, 0, data1->DescriptionW, -1, data1->DescriptionA, sizeof(data1->DescriptionA)-1, NULL, NULL);
377 WideCharToMultiByte(CP_ACP, 0, data1->ModuleW, -1, data1->ModuleA, sizeof(data1->ModuleA)-1, NULL, NULL);
378 data1->DescriptionA[sizeof(data1->DescriptionA)-1] = 0;
379 data1->ModuleA[sizeof(data1->ModuleA)-1] = 0;
380 data1->Type = dataW->Type;
381 data1->DataFlow = dataW->DataFlow;
382 data1->WaveDeviceId = data1->Devnode = dataW->WaveDeviceId;
385 static BOOL CALLBACK DSPROPERTY_enumWtoA(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *descW, void *data)
387 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA descA;
388 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA *ppd = data;
391 ret = DSPROPERTY_descWtoA(descW, &descA);
394 ret = ppd->Callback(&descA, ppd->Context);
395 HeapFree(GetProcessHeap(), 0, descA.Module);
396 HeapFree(GetProcessHeap(), 0, descA.Description);
400 static HRESULT DSPROPERTY_EnumerateA(
405 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA *ppd = pPropData;
406 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA data;
408 if (!ppd || !ppd->Callback)
410 WARN("Invalid ppd %p\n", ppd);
411 return E_PROP_ID_UNSUPPORTED;
414 data.Callback = DSPROPERTY_enumWtoA;
417 return DSPROPERTY_EnumerateW(&data, cbPropData, pcbReturned);
420 static BOOL CALLBACK DSPROPERTY_enumWto1(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *descW, void *data)
422 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA desc1;
423 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA *ppd = data;
426 DSPROPERTY_descWto1(descW, &desc1);
427 ret = ppd->Callback(&desc1, ppd->Context);
431 static HRESULT DSPROPERTY_Enumerate1(
436 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA *ppd = pPropData;
437 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA data;
439 if (!ppd || !ppd->Callback)
441 WARN("Invalid ppd %p\n", ppd);
442 return E_PROP_ID_UNSUPPORTED;
445 data.Callback = DSPROPERTY_enumWto1;
448 return DSPROPERTY_EnumerateW(&data, cbPropData, pcbReturned);
451 static HRESULT DSPROPERTY_DescriptionA(
456 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
457 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *ppd = pPropData;
461 *pcbReturned = sizeof(*ppd);
465 data.DeviceId = ppd->DeviceId;
466 data.DataFlow = ppd->DataFlow;
467 hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
470 if (!DSPROPERTY_descWtoA(&data, ppd))
472 HeapFree(GetProcessHeap(), 0, data.Module);
473 HeapFree(GetProcessHeap(), 0, data.Interface);
477 static HRESULT DSPROPERTY_Description1(
482 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
483 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA *ppd = pPropData;
487 *pcbReturned = sizeof(*ppd);
491 data.DeviceId = ppd->DeviceId;
492 data.DataFlow = ppd->DataFlow;
493 hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
496 DSPROPERTY_descWto1(&data, ppd);
497 HeapFree(GetProcessHeap(), 0, data.Module);
498 HeapFree(GetProcessHeap(), 0, data.Interface);
502 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
503 LPKSPROPERTYSET iface,
506 LPVOID pInstanceData,
507 ULONG cbInstanceData,
512 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
513 TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
514 This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
516 if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
518 case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
519 return DSPROPERTY_WaveDeviceMappingA(pPropData,cbPropData,pcbReturned);
520 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
521 return DSPROPERTY_Description1(pPropData,cbPropData,pcbReturned);
522 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
523 return DSPROPERTY_Enumerate1(pPropData,cbPropData,pcbReturned);
524 case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
525 return DSPROPERTY_WaveDeviceMappingW(pPropData,cbPropData,pcbReturned);
526 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
527 return DSPROPERTY_DescriptionA(pPropData,cbPropData,pcbReturned);
528 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
529 return DSPROPERTY_DescriptionW(pPropData,cbPropData,pcbReturned);
530 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
531 return DSPROPERTY_EnumerateA(pPropData,cbPropData,pcbReturned);
532 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
533 return DSPROPERTY_EnumerateW(pPropData,cbPropData,pcbReturned);
535 FIXME("unsupported ID: %d\n",dwPropID);
539 FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
544 FIXME("*pcbReturned=%d\n", *pcbReturned);
547 return E_PROP_ID_UNSUPPORTED;
550 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
551 LPKSPROPERTYSET iface,
554 LPVOID pInstanceData,
555 ULONG cbInstanceData,
559 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
561 FIXME("(%p,%s,%d,%p,%d,%p,%d), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
562 return E_PROP_ID_UNSUPPORTED;
565 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
566 LPKSPROPERTYSET iface,
569 PULONG pTypeSupport )
571 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
572 TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
574 if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
576 case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
577 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
579 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
580 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
582 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
583 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
585 case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
586 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
588 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
589 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
591 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
592 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
594 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
595 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
597 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
598 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
601 FIXME("unsupported ID: %d\n",dwPropID);
605 FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
608 return E_PROP_ID_UNSUPPORTED;
611 static const IKsPropertySetVtbl ikspvt = {
612 IKsPrivatePropertySetImpl_QueryInterface,
613 IKsPrivatePropertySetImpl_AddRef,
614 IKsPrivatePropertySetImpl_Release,
615 IKsPrivatePropertySetImpl_Get,
616 IKsPrivatePropertySetImpl_Set,
617 IKsPrivatePropertySetImpl_QuerySupport
620 HRESULT IKsPrivatePropertySetImpl_Create(REFIID riid, void **ppv)
622 IKsPrivatePropertySetImpl *iks;
625 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
627 iks = HeapAlloc(GetProcessHeap(), 0, sizeof(*iks));
629 WARN("out of memory\n");
630 return DSERR_OUTOFMEMORY;
634 iks->IKsPropertySet_iface.lpVtbl = &ikspvt;
636 hr = IKsPropertySet_QueryInterface(&iks->IKsPropertySet_iface, riid, ppv);
637 IKsPropertySet_Release(&iks->IKsPropertySet_iface);