ntoskrnl.exe: Send IRP_MN_SURPRISE_REMOVAL to the device stack first.
[wine.git] / dlls / dsdmo / main.c
blobfa39c28abd7c6f7c3e5aa79ac89776bc8e23ef5d
1 /*
2 * Copyright 2019 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
20 #include "dmo.h"
21 #include "mmreg.h"
22 #include "mmsystem.h"
23 #include "uuids.h"
24 #include "initguid.h"
25 #include "dsound.h"
26 #include "rpcproxy.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dsdmo);
32 struct effect
34 IMediaObject IMediaObject_iface;
35 IMediaObjectInPlace IMediaObjectInPlace_iface;
36 IUnknown IUnknown_inner;
37 IUnknown *outer_unk;
38 LONG refcount;
40 CRITICAL_SECTION cs;
41 WAVEFORMATEX format;
43 const struct effect_ops *ops;
46 struct effect_ops
48 void *(*query_interface)(struct effect *effect, REFIID iid);
49 void (*destroy)(struct effect *effect);
52 static struct effect *impl_from_IUnknown(IUnknown *iface)
54 return CONTAINING_RECORD(iface, struct effect, IUnknown_inner);
57 static HRESULT WINAPI effect_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
59 struct effect *effect = impl_from_IUnknown(iface);
61 TRACE("effect %p, iid %s, out %p.\n", effect, debugstr_guid(iid), out);
63 if (IsEqualGUID(iid, &IID_IUnknown))
64 *out = iface;
65 else if (IsEqualGUID(iid, &IID_IMediaObject))
66 *out = &effect->IMediaObject_iface;
67 else if (IsEqualGUID(iid, &IID_IMediaObjectInPlace))
68 *out = &effect->IMediaObjectInPlace_iface;
69 else if (!(*out = effect->ops->query_interface(effect, iid)))
71 WARN("%s not implemented; returning E_NOINTERFACE.\n", debugstr_guid(iid));
72 return E_NOINTERFACE;
75 IUnknown_AddRef((IUnknown *)*out);
76 return S_OK;
79 static ULONG WINAPI effect_inner_AddRef(IUnknown *iface)
81 struct effect *effect = impl_from_IUnknown(iface);
82 ULONG refcount = InterlockedIncrement(&effect->refcount);
84 TRACE("%p increasing refcount to %u.\n", effect, refcount);
85 return refcount;
88 static ULONG WINAPI effect_inner_Release(IUnknown *iface)
90 struct effect *effect = impl_from_IUnknown(iface);
91 ULONG refcount = InterlockedDecrement(&effect->refcount);
93 TRACE("%p decreasing refcount to %u.\n", effect, refcount);
95 if (!refcount)
97 effect->cs.DebugInfo->Spare[0] = 0;
98 DeleteCriticalSection(&effect->cs);
99 effect->ops->destroy(effect);
101 return refcount;
104 static const IUnknownVtbl effect_inner_vtbl =
106 effect_inner_QueryInterface,
107 effect_inner_AddRef,
108 effect_inner_Release,
111 static struct effect *impl_from_IMediaObject(IMediaObject *iface)
113 return CONTAINING_RECORD(iface, struct effect, IMediaObject_iface);
116 static HRESULT WINAPI effect_QueryInterface(IMediaObject *iface, REFIID iid, void **out)
118 struct effect *effect = impl_from_IMediaObject(iface);
119 return IUnknown_QueryInterface(effect->outer_unk, iid, out);
122 static ULONG WINAPI effect_AddRef(IMediaObject *iface)
124 struct effect *effect = impl_from_IMediaObject(iface);
125 return IUnknown_AddRef(effect->outer_unk);
128 static ULONG WINAPI effect_Release(IMediaObject *iface)
130 struct effect *effect = impl_from_IMediaObject(iface);
131 return IUnknown_Release(effect->outer_unk);
134 static HRESULT WINAPI effect_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
136 FIXME("iface %p, input %p, output %p, stub!\n", iface, input, output);
137 return E_NOTIMPL;
140 static HRESULT WINAPI effect_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
142 FIXME("iface %p, index %u, flags %p, stub!\n", iface, index, flags);
143 return E_NOTIMPL;
146 static HRESULT WINAPI effect_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
148 FIXME("iface %p, index %u, flags %p, stub!\n", iface, index, flags);
149 return E_NOTIMPL;
152 static HRESULT WINAPI effect_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type)
154 FIXME("iface %p, index %u, type_index %u, type %p, stub!\n", iface, index, type_index, type);
155 return E_NOTIMPL;
158 static HRESULT WINAPI effect_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type)
160 FIXME("iface %p, index %u, type_index %u, type %p, stub!\n", iface, index, type_index, type);
161 return E_NOTIMPL;
164 static HRESULT WINAPI effect_SetInputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags)
166 struct effect *effect = impl_from_IMediaObject(iface);
167 const WAVEFORMATEX *format;
169 TRACE("iface %p, index %u, type %p, flags %#x.\n", iface, index, type, flags);
171 if (flags & DMO_SET_TYPEF_CLEAR)
173 EnterCriticalSection(&effect->cs);
174 memset(&effect->format, 0, sizeof(effect->format));
175 LeaveCriticalSection(&effect->cs);
176 return S_OK;
179 if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio))
180 return DMO_E_TYPE_NOT_ACCEPTED;
182 if (!IsEqualGUID(&type->subtype, &MEDIASUBTYPE_PCM)
183 && !IsEqualGUID(&type->subtype, &MEDIASUBTYPE_IEEE_FLOAT))
184 return DMO_E_TYPE_NOT_ACCEPTED;
186 if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
187 return DMO_E_TYPE_NOT_ACCEPTED;
189 format = (const WAVEFORMATEX *)type->pbFormat;
190 if (format->wFormatTag == WAVE_FORMAT_PCM)
192 if (format->wBitsPerSample != 8 && format->wBitsPerSample != 16)
194 WARN("Rejecting %u-bit integer PCM.\n", format->wBitsPerSample);
195 return DMO_E_TYPE_NOT_ACCEPTED;
198 else if (format->wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
200 if (format->wBitsPerSample != 32)
202 WARN("Rejecting %u-bit float PCM.\n", format->wBitsPerSample);
203 return DMO_E_TYPE_NOT_ACCEPTED;
206 else
208 WARN("Rejecting tag %#x.\n", format->wFormatTag);
209 return DMO_E_TYPE_NOT_ACCEPTED;
212 if (format->nChannels != 1 && format->nChannels != 2)
214 WARN("Rejecting %u channels.\n", format->nChannels);
215 return DMO_E_TYPE_NOT_ACCEPTED;
218 EnterCriticalSection(&effect->cs);
219 effect->format = *format;
220 LeaveCriticalSection(&effect->cs);
222 return S_OK;
225 static HRESULT WINAPI effect_SetOutputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags)
227 struct effect *effect = impl_from_IMediaObject(iface);
228 HRESULT hr;
230 TRACE("iface %p, index %u, type %p, flags %#x.\n", iface, index, type, flags);
232 if (flags & DMO_SET_TYPEF_CLEAR)
233 return S_OK;
235 if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio))
236 return DMO_E_TYPE_NOT_ACCEPTED;
238 if (!IsEqualGUID(&type->subtype, &MEDIASUBTYPE_PCM)
239 && !IsEqualGUID(&type->subtype, &MEDIASUBTYPE_IEEE_FLOAT))
240 return DMO_E_TYPE_NOT_ACCEPTED;
242 if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
243 return DMO_E_TYPE_NOT_ACCEPTED;
245 EnterCriticalSection(&effect->cs);
246 hr = memcmp(type->pbFormat, &effect->format, sizeof(WAVEFORMATEX)) ? DMO_E_TYPE_NOT_ACCEPTED : S_OK;
247 LeaveCriticalSection(&effect->cs);
249 return hr;
252 static HRESULT WINAPI effect_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
254 FIXME("iface %p, index %u, type %p, stub!\n", iface, index, type);
255 return E_NOTIMPL;
258 static HRESULT WINAPI effect_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
260 FIXME("iface %p, index %u, type %p, stub!\n", iface, index, type);
261 return E_NOTIMPL;
264 static HRESULT WINAPI effect_GetInputSizeInfo(IMediaObject *iface, DWORD index,
265 DWORD *size, DWORD *lookahead, DWORD *alignment)
267 FIXME("iface %p, index %u, size %p, lookahead %p, alignment %p, stub!\n", iface, index, size, lookahead, alignment);
268 return E_NOTIMPL;
271 static HRESULT WINAPI effect_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment)
273 FIXME("iface %p, index %u, size %p, alignment %p, stub!\n", iface, index, size, alignment);
274 return E_NOTIMPL;
277 static HRESULT WINAPI effect_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency)
279 FIXME("iface %p, index %u, latency %p, stub!\n", iface, index, latency);
280 return E_NOTIMPL;
283 static HRESULT WINAPI effect_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency)
285 FIXME("iface %p, index %u, latency %s, stub!\n", iface, index, wine_dbgstr_longlong(latency));
286 return E_NOTIMPL;
289 static HRESULT WINAPI effect_Flush(IMediaObject *iface)
291 FIXME("iface %p, stub!\n", iface);
292 return E_NOTIMPL;
295 static HRESULT WINAPI effect_Discontinuity(IMediaObject *iface, DWORD index)
297 FIXME("iface %p, index %u, stub!\n", iface, index);
298 return E_NOTIMPL;
301 static HRESULT WINAPI effect_AllocateStreamingResources(IMediaObject *iface)
303 FIXME("iface %p, stub!\n", iface);
304 return E_NOTIMPL;
307 static HRESULT WINAPI effect_FreeStreamingResources(IMediaObject *iface)
309 FIXME("iface %p, stub!\n", iface);
310 return E_NOTIMPL;
313 static HRESULT WINAPI effect_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags)
315 FIXME("iface %p, index %u, flags %p, stub!\n", iface, index, flags);
316 return E_NOTIMPL;
319 static HRESULT WINAPI effect_ProcessInput(IMediaObject *iface, DWORD index,
320 IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength)
322 FIXME("iface %p, index %u, buffer %p, flags %#x, timestamp %s, timelength %s, stub!\n",
323 iface, index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength));
324 return E_NOTIMPL;
327 static HRESULT WINAPI effect_ProcessOutput(IMediaObject *iface, DWORD flags,
328 DWORD count, DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
330 FIXME("iface %p, flags %#x, count %u, buffers %p, status %p, stub!\n", iface, flags, count, buffers, status);
331 return E_NOTIMPL;
334 static HRESULT WINAPI effect_Lock(IMediaObject *iface, LONG lock)
336 FIXME("iface %p, lock %d, stub!\n", iface, lock);
337 return E_NOTIMPL;
340 static const IMediaObjectVtbl effect_vtbl =
342 effect_QueryInterface,
343 effect_AddRef,
344 effect_Release,
345 effect_GetStreamCount,
346 effect_GetInputStreamInfo,
347 effect_GetOutputStreamInfo,
348 effect_GetInputType,
349 effect_GetOutputType,
350 effect_SetInputType,
351 effect_SetOutputType,
352 effect_GetInputCurrentType,
353 effect_GetOutputCurrentType,
354 effect_GetInputSizeInfo,
355 effect_GetOutputSizeInfo,
356 effect_GetInputMaxLatency,
357 effect_SetInputMaxLatency,
358 effect_Flush,
359 effect_Discontinuity,
360 effect_AllocateStreamingResources,
361 effect_FreeStreamingResources,
362 effect_GetInputStatus,
363 effect_ProcessInput,
364 effect_ProcessOutput,
365 effect_Lock,
368 static struct effect *impl_from_IMediaObjectInPlace(IMediaObjectInPlace *iface)
370 return CONTAINING_RECORD(iface, struct effect, IMediaObjectInPlace_iface);
373 static HRESULT WINAPI effect_inplace_QueryInterface(IMediaObjectInPlace *iface, REFIID iid, void **out)
375 struct effect *effect = impl_from_IMediaObjectInPlace(iface);
376 return IUnknown_QueryInterface(effect->outer_unk, iid, out);
379 static ULONG WINAPI effect_inplace_AddRef(IMediaObjectInPlace *iface)
381 struct effect *effect = impl_from_IMediaObjectInPlace(iface);
382 return IUnknown_AddRef(effect->outer_unk);
385 static ULONG WINAPI effect_inplace_Release(IMediaObjectInPlace *iface)
387 struct effect *effect = impl_from_IMediaObjectInPlace(iface);
388 return IUnknown_Release(effect->outer_unk);
391 static HRESULT WINAPI effect_inplace_Process(IMediaObjectInPlace *iface, ULONG size,
392 BYTE *data, REFERENCE_TIME start, DWORD flags)
394 FIXME("iface %p, size %u, data %p, start %s, flags %#x, stub!\n",
395 iface, size, data, wine_dbgstr_longlong(start), flags);
396 return E_NOTIMPL;
399 static HRESULT WINAPI effect_inplace_Clone(IMediaObjectInPlace *iface, IMediaObjectInPlace **out)
401 FIXME("iface %p, out %p, stub!\n", iface, out);
402 return E_NOTIMPL;
405 static HRESULT WINAPI effect_inplace_GetLatency(IMediaObjectInPlace *iface, REFERENCE_TIME *latency)
407 FIXME("iface %p, latency %p, stub!\n", iface, latency);
408 return E_NOTIMPL;
411 static const IMediaObjectInPlaceVtbl effect_inplace_vtbl =
413 effect_inplace_QueryInterface,
414 effect_inplace_AddRef,
415 effect_inplace_Release,
416 effect_inplace_Process,
417 effect_inplace_Clone,
418 effect_inplace_GetLatency,
421 static void effect_init(struct effect *effect, IUnknown *outer, const struct effect_ops *ops)
423 effect->outer_unk = outer ? outer : &effect->IUnknown_inner;
424 effect->refcount = 1;
425 effect->IUnknown_inner.lpVtbl = &effect_inner_vtbl;
426 effect->IMediaObject_iface.lpVtbl = &effect_vtbl;
427 effect->IMediaObjectInPlace_iface.lpVtbl = &effect_inplace_vtbl;
429 InitializeCriticalSection(&effect->cs);
430 effect->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": effect.cs");
432 effect->ops = ops;
435 struct eq
437 struct effect effect;
438 IDirectSoundFXParamEq IDirectSoundFXParamEq_iface;
439 DSFXParamEq params;
442 static struct eq *impl_from_IDirectSoundFXParamEq(IDirectSoundFXParamEq *iface)
444 return CONTAINING_RECORD(iface, struct eq, IDirectSoundFXParamEq_iface);
447 static HRESULT WINAPI eq_params_QueryInterface(IDirectSoundFXParamEq *iface, REFIID iid, void **out)
449 struct eq *effect = impl_from_IDirectSoundFXParamEq(iface);
450 return IUnknown_QueryInterface(effect->effect.outer_unk, iid, out);
453 static ULONG WINAPI eq_params_AddRef(IDirectSoundFXParamEq *iface)
455 struct eq *effect = impl_from_IDirectSoundFXParamEq(iface);
456 return IUnknown_AddRef(effect->effect.outer_unk);
459 static ULONG WINAPI eq_params_Release(IDirectSoundFXParamEq *iface)
461 struct eq *effect = impl_from_IDirectSoundFXParamEq(iface);
462 return IUnknown_Release(effect->effect.outer_unk);
465 static HRESULT WINAPI eq_params_SetAllParameters(IDirectSoundFXParamEq *iface, const DSFXParamEq *params)
467 struct eq *effect = impl_from_IDirectSoundFXParamEq(iface);
469 TRACE("effect %p, params %p.\n", effect, params);
471 EnterCriticalSection(&effect->effect.cs);
472 effect->params = *params;
473 LeaveCriticalSection(&effect->effect.cs);
474 return S_OK;
477 static HRESULT WINAPI eq_params_GetAllParameters(IDirectSoundFXParamEq *iface, DSFXParamEq *params)
479 struct eq *effect = impl_from_IDirectSoundFXParamEq(iface);
481 TRACE("effect %p, params %p.\n", effect, params);
483 EnterCriticalSection(&effect->effect.cs);
484 *params = effect->params;
485 LeaveCriticalSection(&effect->effect.cs);
486 return S_OK;
489 static const IDirectSoundFXParamEqVtbl eq_params_vtbl =
491 eq_params_QueryInterface,
492 eq_params_AddRef,
493 eq_params_Release,
494 eq_params_SetAllParameters,
495 eq_params_GetAllParameters,
498 static struct eq *impl_eq_from_effect(struct effect *iface)
500 return CONTAINING_RECORD(iface, struct eq, effect);
503 static void *eq_query_interface(struct effect *iface, REFIID iid)
505 struct eq *effect = impl_eq_from_effect(iface);
507 if (IsEqualGUID(iid, &IID_IDirectSoundFXParamEq))
508 return &effect->IDirectSoundFXParamEq_iface;
509 return NULL;
512 static void eq_destroy(struct effect *iface)
514 struct eq *effect = impl_eq_from_effect(iface);
516 free(effect);
519 static const struct effect_ops eq_ops =
521 .destroy = eq_destroy,
522 .query_interface = eq_query_interface,
525 static HRESULT eq_create(IUnknown *outer, IUnknown **out)
527 struct eq *object;
529 if (!(object = calloc(1, sizeof(*object))))
530 return E_OUTOFMEMORY;
532 effect_init(&object->effect, outer, &eq_ops);
533 object->IDirectSoundFXParamEq_iface.lpVtbl = &eq_params_vtbl;
535 object->params.fCenter = 8000.0f;
536 object->params.fBandwidth = 12.0f;
537 object->params.fGain = 0.0f;
539 TRACE("Created equalizer effect %p.\n", object);
540 *out = &object->effect.IUnknown_inner;
541 return S_OK;
544 struct reverb
546 struct effect effect;
547 IDirectSoundFXI3DL2Reverb IDirectSoundFXI3DL2Reverb_iface;
548 DSFXI3DL2Reverb params;
551 static struct reverb *impl_from_IDirectSoundFXI3DL2Reverb(IDirectSoundFXI3DL2Reverb *iface)
553 return CONTAINING_RECORD(iface, struct reverb, IDirectSoundFXI3DL2Reverb_iface);
556 static HRESULT WINAPI reverb_params_QueryInterface(IDirectSoundFXI3DL2Reverb *iface, REFIID iid, void **out)
558 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
559 return IUnknown_QueryInterface(effect->effect.outer_unk, iid, out);
562 static ULONG WINAPI reverb_params_AddRef(IDirectSoundFXI3DL2Reverb *iface)
564 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
565 return IUnknown_AddRef(effect->effect.outer_unk);
568 static ULONG WINAPI reverb_params_Release(IDirectSoundFXI3DL2Reverb *iface)
570 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
571 return IUnknown_Release(effect->effect.outer_unk);
574 static HRESULT WINAPI reverb_params_SetAllParameters(IDirectSoundFXI3DL2Reverb *iface, const DSFXI3DL2Reverb *params)
576 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
578 TRACE("effect %p, params %p.\n", effect, params);
580 EnterCriticalSection(&effect->effect.cs);
581 effect->params = *params;
582 LeaveCriticalSection(&effect->effect.cs);
583 return S_OK;
586 static HRESULT WINAPI reverb_params_GetAllParameters(IDirectSoundFXI3DL2Reverb *iface, DSFXI3DL2Reverb *params)
588 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
590 TRACE("effect %p, params %p.\n", effect, params);
592 EnterCriticalSection(&effect->effect.cs);
593 *params = effect->params;
594 LeaveCriticalSection(&effect->effect.cs);
595 return S_OK;
598 static HRESULT WINAPI reverb_params_SetPreset(IDirectSoundFXI3DL2Reverb *iface, DWORD preset)
600 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
602 FIXME("effect %p, preset %u, stub!\n", effect, preset);
604 return E_NOTIMPL;
607 static HRESULT WINAPI reverb_params_GetPreset(IDirectSoundFXI3DL2Reverb *iface, DWORD *preset)
609 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
611 FIXME("effect %p, preset %p, stub!\n", effect, preset);
613 return E_NOTIMPL;
616 static HRESULT WINAPI reverb_params_SetQuality(IDirectSoundFXI3DL2Reverb *iface, LONG quality)
618 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
620 FIXME("effect %p, quality %u, stub!\n", effect, quality);
622 return E_NOTIMPL;
625 static HRESULT WINAPI reverb_params_GetQuality(IDirectSoundFXI3DL2Reverb *iface, LONG *quality)
627 struct reverb *effect = impl_from_IDirectSoundFXI3DL2Reverb(iface);
629 FIXME("effect %p, quality %p, stub!\n", effect, quality);
631 return E_NOTIMPL;
634 static const IDirectSoundFXI3DL2ReverbVtbl reverb_params_vtbl =
636 reverb_params_QueryInterface,
637 reverb_params_AddRef,
638 reverb_params_Release,
639 reverb_params_SetAllParameters,
640 reverb_params_GetAllParameters,
641 reverb_params_SetPreset,
642 reverb_params_GetPreset,
643 reverb_params_SetQuality,
644 reverb_params_GetQuality,
647 static struct reverb *impl_reverb_from_effect(struct effect *iface)
649 return CONTAINING_RECORD(iface, struct reverb, effect);
652 static void *reverb_query_interface(struct effect *iface, REFIID iid)
654 struct reverb *effect = impl_reverb_from_effect(iface);
656 if (IsEqualGUID(iid, &IID_IDirectSoundFXI3DL2Reverb))
657 return &effect->IDirectSoundFXI3DL2Reverb_iface;
658 return NULL;
661 static void reverb_destroy(struct effect *iface)
663 struct reverb *effect = impl_reverb_from_effect(iface);
665 free(effect);
668 static const struct effect_ops reverb_ops =
670 .destroy = reverb_destroy,
671 .query_interface = reverb_query_interface,
674 static HRESULT reverb_create(IUnknown *outer, IUnknown **out)
676 struct reverb *object;
678 if (!(object = calloc(1, sizeof(*object))))
679 return E_OUTOFMEMORY;
681 effect_init(&object->effect, outer, &reverb_ops);
682 object->IDirectSoundFXI3DL2Reverb_iface.lpVtbl = &reverb_params_vtbl;
684 object->params.lRoom = DSFX_I3DL2REVERB_ROOM_DEFAULT;
685 object->params.lRoomHF = DSFX_I3DL2REVERB_ROOMHF_DEFAULT;
686 object->params.flRoomRolloffFactor = DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_DEFAULT;
687 object->params.flDecayTime = DSFX_I3DL2REVERB_DECAYTIME_DEFAULT;
688 object->params.flDecayHFRatio = DSFX_I3DL2REVERB_DECAYHFRATIO_DEFAULT;
689 object->params.lReflections = DSFX_I3DL2REVERB_REFLECTIONS_DEFAULT;
690 object->params.flReflectionsDelay = DSFX_I3DL2REVERB_REFLECTIONSDELAY_DEFAULT;
691 object->params.lReverb = DSFX_I3DL2REVERB_REVERB_DEFAULT;
692 object->params.flReverbDelay = DSFX_I3DL2REVERB_REVERBDELAY_DEFAULT;
693 object->params.flDiffusion = DSFX_I3DL2REVERB_DIFFUSION_DEFAULT;
694 object->params.flDensity = DSFX_I3DL2REVERB_DENSITY_DEFAULT;
695 object->params.flHFReference = DSFX_I3DL2REVERB_HFREFERENCE_DEFAULT;
697 TRACE("Created I3DL2 reverb effect %p.\n", object);
698 *out = &object->effect.IUnknown_inner;
699 return S_OK;
702 struct waves_reverb
704 struct effect effect;
705 IDirectSoundFXWavesReverb IDirectSoundFXWavesReverb_iface;
708 static struct waves_reverb *impl_from_IDirectSoundFXWavesReverb(IDirectSoundFXWavesReverb *iface)
710 return CONTAINING_RECORD(iface, struct waves_reverb, IDirectSoundFXWavesReverb_iface);
713 static HRESULT WINAPI waves_reverb_params_QueryInterface(IDirectSoundFXWavesReverb *iface, REFIID iid, void **out)
715 struct waves_reverb *effect = impl_from_IDirectSoundFXWavesReverb(iface);
716 return IUnknown_QueryInterface(effect->effect.outer_unk, iid, out);
719 static ULONG WINAPI waves_reverb_params_AddRef(IDirectSoundFXWavesReverb *iface)
721 struct waves_reverb *effect = impl_from_IDirectSoundFXWavesReverb(iface);
722 return IUnknown_AddRef(effect->effect.outer_unk);
725 static ULONG WINAPI waves_reverb_params_Release(IDirectSoundFXWavesReverb *iface)
727 struct waves_reverb *effect = impl_from_IDirectSoundFXWavesReverb(iface);
728 return IUnknown_Release(effect->effect.outer_unk);
731 static HRESULT WINAPI waves_reverb_params_SetAllParameters(IDirectSoundFXWavesReverb *iface, const DSFXWavesReverb *params)
733 struct waves_reverb *effect = impl_from_IDirectSoundFXWavesReverb(iface);
735 FIXME("effect %p, params %p, stub!\n", effect, params);
737 return E_NOTIMPL;
740 static HRESULT WINAPI waves_reverb_params_GetAllParameters(IDirectSoundFXWavesReverb *iface, DSFXWavesReverb *params)
742 struct waves_reverb *effect = impl_from_IDirectSoundFXWavesReverb(iface);
744 FIXME("effect %p, params %p, stub!\n", effect, params);
746 return E_NOTIMPL;
749 static const IDirectSoundFXWavesReverbVtbl waves_reverb_params_vtbl =
751 waves_reverb_params_QueryInterface,
752 waves_reverb_params_AddRef,
753 waves_reverb_params_Release,
754 waves_reverb_params_SetAllParameters,
755 waves_reverb_params_GetAllParameters,
758 static struct waves_reverb *impl_waves_reverb_from_effect(struct effect *iface)
760 return CONTAINING_RECORD(iface, struct waves_reverb, effect);
763 static void *waves_reverb_query_interface(struct effect *iface, REFIID iid)
765 struct waves_reverb *effect = impl_waves_reverb_from_effect(iface);
767 if (IsEqualGUID(iid, &IID_IDirectSoundFXWavesReverb))
768 return &effect->IDirectSoundFXWavesReverb_iface;
769 return NULL;
772 static void waves_reverb_destroy(struct effect *iface)
774 struct waves_reverb *effect = impl_waves_reverb_from_effect(iface);
776 free(effect);
779 static const struct effect_ops waves_reverb_ops =
781 .destroy = waves_reverb_destroy,
782 .query_interface = waves_reverb_query_interface,
785 static HRESULT waves_reverb_create(IUnknown *outer, IUnknown **out)
787 struct waves_reverb *object;
789 if (!(object = calloc(1, sizeof(*object))))
790 return E_OUTOFMEMORY;
792 effect_init(&object->effect, outer, &waves_reverb_ops);
793 object->IDirectSoundFXWavesReverb_iface.lpVtbl = &waves_reverb_params_vtbl;
795 TRACE("Created waves reverb effect %p.\n", object);
796 *out = &object->effect.IUnknown_inner;
797 return S_OK;
800 struct class_factory
802 IClassFactory IClassFactory_iface;
803 HRESULT (*create_instance)(IUnknown *outer, IUnknown **out);
806 static struct class_factory *impl_from_IClassFactory(IClassFactory *iface)
808 return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface);
811 static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
813 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
815 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
817 IClassFactory_AddRef(iface);
818 *out = iface;
819 return S_OK;
822 *out = NULL;
823 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(iid));
824 return E_NOINTERFACE;
827 static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
829 return 2;
832 static ULONG WINAPI class_factory_Release(IClassFactory *iface)
834 return 1;
837 static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface,
838 IUnknown *outer, REFIID iid, void **out)
840 struct class_factory *factory = impl_from_IClassFactory(iface);
841 IUnknown *unk;
842 HRESULT hr;
844 TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out);
846 *out = NULL;
848 if (outer && !IsEqualGUID(iid, &IID_IUnknown))
849 return E_NOINTERFACE;
851 if (SUCCEEDED(hr = factory->create_instance(outer, &unk)))
853 hr = IUnknown_QueryInterface(unk, iid, out);
854 IUnknown_Release(unk);
856 return hr;
859 static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL lock)
861 FIXME("lock %d, stub!\n", lock);
862 return S_OK;
865 static const IClassFactoryVtbl class_factory_vtbl =
867 class_factory_QueryInterface,
868 class_factory_AddRef,
869 class_factory_Release,
870 class_factory_CreateInstance,
871 class_factory_LockServer,
874 static struct
876 const GUID *clsid;
877 struct class_factory factory;
879 class_factories[] =
881 {&GUID_DSFX_STANDARD_I3DL2REVERB, {{&class_factory_vtbl}, reverb_create}},
882 {&GUID_DSFX_STANDARD_PARAMEQ, {{&class_factory_vtbl}, eq_create}},
883 {&GUID_DSFX_WAVES_REVERB, {{&class_factory_vtbl}, waves_reverb_create}},
886 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
888 unsigned int i;
890 TRACE("clsid %s, iid %s, out %p.\n", debugstr_guid(clsid), debugstr_guid(iid), out);
892 for (i = 0; i < ARRAY_SIZE(class_factories); ++i)
894 if (IsEqualGUID(clsid, class_factories[i].clsid))
895 return IClassFactory_QueryInterface(&class_factories[i].factory.IClassFactory_iface, iid, out);
898 FIXME("%s not available, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid));
899 return CLASS_E_CLASSNOTAVAILABLE;