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 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
46 static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 };
48 typedef struct IKsPrivatePropertySetImpl
50 IKsPropertySet IKsPropertySet_iface;
52 } IKsPrivatePropertySetImpl;
54 static IKsPrivatePropertySetImpl *impl_from_IKsPropertySet(IKsPropertySet *iface)
56 return CONTAINING_RECORD(iface, IKsPrivatePropertySetImpl, IKsPropertySet_iface);
59 /*******************************************************************************
60 * IKsPrivatePropertySet
63 /* IUnknown methods */
64 static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface(
65 IKsPropertySet *iface, REFIID riid, void **ppobj)
67 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
68 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
70 if (IsEqualIID(riid, &IID_IUnknown) ||
71 IsEqualIID(riid, &IID_IKsPropertySet)) {
73 IKsPropertySet_AddRef(iface);
80 static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface)
82 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
83 ULONG ref = InterlockedIncrement(&(This->ref));
84 TRACE("(%p) ref was %d\n", This, ref - 1);
88 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
90 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
91 ULONG ref = InterlockedDecrement(&(This->ref));
92 TRACE("(%p) ref was %d\n", This, ref + 1);
95 HeapFree(GetProcessHeap(), 0, This);
96 TRACE("(%p) released\n", This);
102 const WCHAR *tgt_name;
106 static BOOL CALLBACK search_callback(GUID *guid, const WCHAR *desc,
107 const WCHAR *module, void *user)
109 struct search_data *search = user;
111 if(!lstrcmpW(desc, search->tgt_name)){
112 *search->found_guid = *guid;
119 static HRESULT DSPROPERTY_WaveDeviceMappingW(
125 PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd = pPropData;
126 struct search_data search;
128 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
129 pPropData,cbPropData,pcbReturned);
132 WARN("invalid parameter: pPropData\n");
133 return DSERR_INVALIDPARAM;
136 search.tgt_name = ppd->DeviceName;
137 search.found_guid = &ppd->DeviceId;
139 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER)
140 hr = enumerate_mmdevices(eRender, DSOUND_renderer_guids,
141 search_callback, &search);
142 else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE)
143 hr = enumerate_mmdevices(eCapture, DSOUND_capture_guids,
144 search_callback, &search);
146 return DSERR_INVALIDPARAM;
149 /* device was not found */
150 return DSERR_INVALIDPARAM;
153 *pcbReturned = cbPropData;
158 static HRESULT DSPROPERTY_WaveDeviceMappingA(
163 DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA *ppd = pPropData;
164 DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA data;
168 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
169 pPropData,cbPropData,pcbReturned);
171 if (!ppd || !ppd->DeviceName) {
172 WARN("invalid parameter: ppd=%p\n", ppd);
173 return DSERR_INVALIDPARAM;
176 data.DataFlow = ppd->DataFlow;
177 len = MultiByteToWideChar(CP_ACP, 0, ppd->DeviceName, -1, NULL, 0);
178 data.DeviceName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
179 if (!data.DeviceName)
180 return E_OUTOFMEMORY;
181 MultiByteToWideChar(CP_ACP, 0, ppd->DeviceName, -1, data.DeviceName, len);
183 hr = DSPROPERTY_WaveDeviceMappingW(&data, cbPropData, pcbReturned);
184 HeapFree(GetProcessHeap(), 0, data.DeviceName);
185 ppd->DeviceId = data.DeviceId;
188 *pcbReturned = cbPropData;
193 static HRESULT DSPROPERTY_DescriptionW(
198 PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = pPropData;
206 TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
207 pPropData,cbPropData,pcbReturned);
209 TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
210 if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
211 /* default device of type specified by ppd->DataFlow */
212 if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
213 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
214 ppd->DeviceId = DSDEVID_DefaultCapture;
215 } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
216 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
217 ppd->DeviceId = DSDEVID_DefaultPlayback;
219 WARN("DataFlow=Unknown(%d)\n", ppd->DataFlow);
220 return E_PROP_ID_UNSUPPORTED;
224 setup_dsound_options();
226 GetDeviceID(&ppd->DeviceId, &dev_guid);
228 hr = get_mmdevice(eRender, &dev_guid, &mmdevice);
230 hr = get_mmdevice(eCapture, &dev_guid, &mmdevice);
235 hr = IMMDevice_OpenPropertyStore(mmdevice, STGM_READ, &ps);
237 IMMDevice_Release(mmdevice);
238 WARN("OpenPropertyStore failed: %08x\n", hr);
242 hr = IPropertyStore_GetValue(ps,
243 (const PROPERTYKEY *)&DEVPKEY_Device_FriendlyName, &pv);
245 IPropertyStore_Release(ps);
246 IMMDevice_Release(mmdevice);
247 WARN("GetValue(FriendlyName) failed: %08x\n", hr);
251 desclen = lstrlenW(pv.u.pwszVal) + 1;
252 /* FIXME: Still a memory leak.. */
253 ppd->Description = HeapAlloc(GetProcessHeap(), 0, desclen * sizeof(WCHAR));
254 memcpy(ppd->Description, pv.u.pwszVal, desclen * sizeof(WCHAR));
255 ppd->Module = wine_vxd_drv;
256 ppd->Interface = wInterface;
257 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
259 PropVariantClear(&pv);
260 IPropertyStore_Release(ps);
261 IMMDevice_Release(mmdevice);
264 *pcbReturned = sizeof(*ppd);
265 TRACE("*pcbReturned=%d\n", *pcbReturned);
272 BOOL CALLBACK enum_callback(GUID *guid, const WCHAR *desc, const WCHAR *module,
275 PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = user;
276 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
280 TRACE("%s %s %s %p\n", wine_dbgstr_guid(guid), wine_dbgstr_w(desc),
281 wine_dbgstr_w(module), user);
286 data.DeviceId = *guid;
288 len = lstrlenW(module) + 1;
289 data.Module = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
290 memcpy(data.Module, module, len * sizeof(WCHAR));
292 len = lstrlenW(desc) + 1;
293 data.Description = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
294 memcpy(data.Description, desc, len * sizeof(WCHAR));
296 data.Interface = wInterface;
298 ret = ppd->Callback(&data, ppd->Context);
300 HeapFree(GetProcessHeap(), 0, data.Module);
301 HeapFree(GetProcessHeap(), 0, data.Description);
306 static HRESULT DSPROPERTY_EnumerateW(
311 PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData;
314 TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
315 pPropData,cbPropData,pcbReturned);
320 if (!ppd || !ppd->Callback)
322 WARN("Invalid ppd %p\n", ppd);
323 return E_PROP_ID_UNSUPPORTED;
326 hr = enumerate_mmdevices(eRender, DSOUND_renderer_guids,
330 hr = enumerate_mmdevices(eCapture, DSOUND_capture_guids,
333 return SUCCEEDED(hr) ? DS_OK : hr;
336 static BOOL DSPROPERTY_descWtoA(const DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW,
337 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *dataA)
339 DWORD modlen, desclen;
340 static char Interface[] = "Interface";
342 modlen = WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, NULL, 0, NULL, NULL);
343 desclen = WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, NULL, 0, NULL, NULL);
344 dataA->Type = dataW->Type;
345 dataA->DataFlow = dataW->DataFlow;
346 dataA->DeviceId = dataW->DeviceId;
347 dataA->WaveDeviceId = dataW->WaveDeviceId;
348 dataA->Interface = Interface;
349 dataA->Module = HeapAlloc(GetProcessHeap(), 0, modlen);
350 dataA->Description = HeapAlloc(GetProcessHeap(), 0, desclen);
351 if (!dataA->Module || !dataA->Description)
353 HeapFree(GetProcessHeap(), 0, dataA->Module);
354 HeapFree(GetProcessHeap(), 0, dataA->Description);
355 dataA->Module = dataA->Description = NULL;
359 WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, dataA->Module, modlen, NULL, NULL);
360 WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, dataA->Description, desclen, NULL, NULL);
364 static void DSPROPERTY_descWto1(const DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW,
365 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA *data1)
367 data1->DeviceId = dataW->DeviceId;
368 lstrcpynW(data1->ModuleW, dataW->Module, sizeof(data1->ModuleW)/sizeof(*data1->ModuleW));
369 lstrcpynW(data1->DescriptionW, dataW->Description, sizeof(data1->DescriptionW)/sizeof(*data1->DescriptionW));
370 WideCharToMultiByte(CP_ACP, 0, data1->DescriptionW, -1, data1->DescriptionA, sizeof(data1->DescriptionA)-1, NULL, NULL);
371 WideCharToMultiByte(CP_ACP, 0, data1->ModuleW, -1, data1->ModuleA, sizeof(data1->ModuleA)-1, NULL, NULL);
372 data1->DescriptionA[sizeof(data1->DescriptionA)-1] = 0;
373 data1->ModuleA[sizeof(data1->ModuleA)-1] = 0;
374 data1->Type = dataW->Type;
375 data1->DataFlow = dataW->DataFlow;
376 data1->WaveDeviceId = data1->Devnode = dataW->WaveDeviceId;
379 static BOOL CALLBACK DSPROPERTY_enumWtoA(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *descW, void *data)
381 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA descA;
382 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA *ppd = data;
385 ret = DSPROPERTY_descWtoA(descW, &descA);
388 ret = ppd->Callback(&descA, ppd->Context);
389 HeapFree(GetProcessHeap(), 0, descA.Module);
390 HeapFree(GetProcessHeap(), 0, descA.Description);
394 static HRESULT DSPROPERTY_EnumerateA(
399 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA *ppd = pPropData;
400 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA data;
402 if (!ppd || !ppd->Callback)
404 WARN("Invalid ppd %p\n", ppd);
405 return E_PROP_ID_UNSUPPORTED;
408 data.Callback = DSPROPERTY_enumWtoA;
411 return DSPROPERTY_EnumerateW(&data, cbPropData, pcbReturned);
414 static BOOL CALLBACK DSPROPERTY_enumWto1(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *descW, void *data)
416 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA desc1;
417 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA *ppd = data;
420 DSPROPERTY_descWto1(descW, &desc1);
421 ret = ppd->Callback(&desc1, ppd->Context);
425 static HRESULT DSPROPERTY_Enumerate1(
430 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA *ppd = pPropData;
431 DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA data;
433 if (!ppd || !ppd->Callback)
435 WARN("Invalid ppd %p\n", ppd);
436 return E_PROP_ID_UNSUPPORTED;
439 data.Callback = DSPROPERTY_enumWto1;
442 return DSPROPERTY_EnumerateW(&data, cbPropData, pcbReturned);
445 static HRESULT DSPROPERTY_DescriptionA(
450 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
451 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *ppd = pPropData;
455 *pcbReturned = sizeof(*ppd);
459 data.DeviceId = ppd->DeviceId;
460 data.DataFlow = ppd->DataFlow;
461 hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
464 if (!DSPROPERTY_descWtoA(&data, ppd))
466 HeapFree(GetProcessHeap(), 0, data.Module);
467 HeapFree(GetProcessHeap(), 0, data.Interface);
471 static HRESULT DSPROPERTY_Description1(
476 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
477 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA *ppd = pPropData;
481 *pcbReturned = sizeof(*ppd);
485 data.DeviceId = ppd->DeviceId;
486 data.DataFlow = ppd->DataFlow;
487 hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
490 DSPROPERTY_descWto1(&data, ppd);
491 HeapFree(GetProcessHeap(), 0, data.Module);
492 HeapFree(GetProcessHeap(), 0, data.Interface);
496 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
497 LPKSPROPERTYSET iface,
500 LPVOID pInstanceData,
501 ULONG cbInstanceData,
506 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
507 TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
508 This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
510 if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
512 case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
513 return DSPROPERTY_WaveDeviceMappingA(pPropData,cbPropData,pcbReturned);
514 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
515 return DSPROPERTY_Description1(pPropData,cbPropData,pcbReturned);
516 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
517 return DSPROPERTY_Enumerate1(pPropData,cbPropData,pcbReturned);
518 case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
519 return DSPROPERTY_WaveDeviceMappingW(pPropData,cbPropData,pcbReturned);
520 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
521 return DSPROPERTY_DescriptionA(pPropData,cbPropData,pcbReturned);
522 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
523 return DSPROPERTY_DescriptionW(pPropData,cbPropData,pcbReturned);
524 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
525 return DSPROPERTY_EnumerateA(pPropData,cbPropData,pcbReturned);
526 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
527 return DSPROPERTY_EnumerateW(pPropData,cbPropData,pcbReturned);
529 FIXME("unsupported ID: %d\n",dwPropID);
533 FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
538 FIXME("*pcbReturned=%d\n", *pcbReturned);
541 return E_PROP_ID_UNSUPPORTED;
544 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
545 LPKSPROPERTYSET iface,
548 LPVOID pInstanceData,
549 ULONG cbInstanceData,
553 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
555 FIXME("(%p,%s,%d,%p,%d,%p,%d), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
556 return E_PROP_ID_UNSUPPORTED;
559 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
560 LPKSPROPERTYSET iface,
563 PULONG pTypeSupport )
565 IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
566 TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
568 if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
570 case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
571 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
573 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
574 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
576 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
577 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
579 case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
580 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
582 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
583 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
585 case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
586 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
588 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
589 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
591 case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
592 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
595 FIXME("unsupported ID: %d\n",dwPropID);
599 FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
602 return E_PROP_ID_UNSUPPORTED;
605 static const IKsPropertySetVtbl ikspvt = {
606 IKsPrivatePropertySetImpl_QueryInterface,
607 IKsPrivatePropertySetImpl_AddRef,
608 IKsPrivatePropertySetImpl_Release,
609 IKsPrivatePropertySetImpl_Get,
610 IKsPrivatePropertySetImpl_Set,
611 IKsPrivatePropertySetImpl_QuerySupport
614 HRESULT IKsPrivatePropertySetImpl_Create(REFIID riid, void **ppv)
616 IKsPrivatePropertySetImpl *iks;
619 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
621 iks = HeapAlloc(GetProcessHeap(), 0, sizeof(*iks));
623 WARN("out of memory\n");
624 return DSERR_OUTOFMEMORY;
628 iks->IKsPropertySet_iface.lpVtbl = &ikspvt;
630 hr = IKsPropertySet_QueryInterface(&iks->IKsPropertySet_iface, riid, ppv);
631 IKsPropertySet_Release(&iks->IKsPropertySet_iface);