msxml3: Put together similar tests using tabled test data.
[wine] / dlls / mmdevapi / main.c
1 /*
2  * Copyright 2009 Maarten Lankhorst
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <stdarg.h>
23
24 #ifdef HAVE_AL_AL_H
25 #include <AL/al.h>
26 #include <AL/alc.h>
27 #elif defined(HAVE_OPENAL_AL_H)
28 #include <OpenAL/al.h>
29 #include <OpenAL/alc.h>
30 #endif
31
32 #define COBJMACROS
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wingdi.h"
36 #include "wine/library.h"
37
38 #include "ole2.h"
39 #include "olectl.h"
40 #include "rpcproxy.h"
41 #include "propsys.h"
42 #include "initguid.h"
43 #include "propkeydef.h"
44 #include "mmdeviceapi.h"
45 #include "dshow.h"
46 #include "dsound.h"
47 #include "audioclient.h"
48 #include "endpointvolume.h"
49 #include "audiopolicy.h"
50 #include "devpkey.h"
51
52 #include "mmdevapi.h"
53 #include "wine/debug.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
56
57 #ifdef HAVE_OPENAL
58
59 int local_contexts;
60
61 static CRITICAL_SECTION_DEBUG openal_crst_debug =
62 {
63     0, 0, &openal_crst,
64     { &openal_crst_debug.ProcessLocksList,
65       &openal_crst_debug.ProcessLocksList },
66       0, 0, { (DWORD_PTR)(__FILE__ ": openal_crst_debug") }
67 };
68 CRITICAL_SECTION openal_crst = { &openal_crst_debug, -1, 0, 0, 0, 0 };
69
70 static void *openal_handle = RTLD_DEFAULT;
71 int openal_loaded;
72 #ifdef SONAME_LIBOPENAL
73 LPALCCREATECONTEXT palcCreateContext = NULL;
74 LPALCMAKECONTEXTCURRENT palcMakeContextCurrent = NULL;
75 LPALCPROCESSCONTEXT palcProcessContext = NULL;
76 LPALCSUSPENDCONTEXT palcSuspendContext = NULL;
77 LPALCDESTROYCONTEXT palcDestroyContext = NULL;
78 LPALCGETCURRENTCONTEXT palcGetCurrentContext = NULL;
79 LPALCGETCONTEXTSDEVICE palcGetContextsDevice = NULL;
80 LPALCOPENDEVICE palcOpenDevice = NULL;
81 LPALCCLOSEDEVICE palcCloseDevice = NULL;
82 LPALCGETERROR palcGetError = NULL;
83 LPALCISEXTENSIONPRESENT palcIsExtensionPresent = NULL;
84 LPALCGETPROCADDRESS palcGetProcAddress = NULL;
85 LPALCGETENUMVALUE palcGetEnumValue = NULL;
86 LPALCGETSTRING palcGetString = NULL;
87 LPALCGETINTEGERV palcGetIntegerv = NULL;
88 LPALCCAPTUREOPENDEVICE palcCaptureOpenDevice = NULL;
89 LPALCCAPTURECLOSEDEVICE palcCaptureCloseDevice = NULL;
90 LPALCCAPTURESTART palcCaptureStart = NULL;
91 LPALCCAPTURESTOP palcCaptureStop = NULL;
92 LPALCCAPTURESAMPLES palcCaptureSamples = NULL;
93 LPALENABLE palEnable = NULL;
94 LPALDISABLE palDisable = NULL;
95 LPALISENABLED palIsEnabled = NULL;
96 LPALGETSTRING palGetString = NULL;
97 LPALGETBOOLEANV palGetBooleanv = NULL;
98 LPALGETINTEGERV palGetIntegerv = NULL;
99 LPALGETFLOATV palGetFloatv = NULL;
100 LPALGETDOUBLEV palGetDoublev = NULL;
101 LPALGETBOOLEAN palGetBoolean = NULL;
102 LPALGETINTEGER palGetInteger = NULL;
103 LPALGETFLOAT palGetFloat = NULL;
104 LPALGETDOUBLE palGetDouble = NULL;
105 LPALGETERROR palGetError = NULL;
106 LPALISEXTENSIONPRESENT palIsExtensionPresent = NULL;
107 LPALGETPROCADDRESS palGetProcAddress = NULL;
108 LPALGETENUMVALUE palGetEnumValue = NULL;
109 LPALLISTENERF palListenerf = NULL;
110 LPALLISTENER3F palListener3f = NULL;
111 LPALLISTENERFV palListenerfv = NULL;
112 LPALLISTENERI palListeneri = NULL;
113 LPALLISTENER3I palListener3i = NULL;
114 LPALLISTENERIV palListeneriv = NULL;
115 LPALGETLISTENERF palGetListenerf = NULL;
116 LPALGETLISTENER3F palGetListener3f = NULL;
117 LPALGETLISTENERFV palGetListenerfv = NULL;
118 LPALGETLISTENERI palGetListeneri = NULL;
119 LPALGETLISTENER3I palGetListener3i = NULL;
120 LPALGETLISTENERIV palGetListeneriv = NULL;
121 LPALGENSOURCES palGenSources = NULL;
122 LPALDELETESOURCES palDeleteSources = NULL;
123 LPALISSOURCE palIsSource = NULL;
124 LPALSOURCEF palSourcef = NULL;
125 LPALSOURCE3F palSource3f = NULL;
126 LPALSOURCEFV palSourcefv = NULL;
127 LPALSOURCEI palSourcei = NULL;
128 LPALSOURCE3I palSource3i = NULL;
129 LPALSOURCEIV palSourceiv = NULL;
130 LPALGETSOURCEF palGetSourcef = NULL;
131 LPALGETSOURCE3F palGetSource3f = NULL;
132 LPALGETSOURCEFV palGetSourcefv = NULL;
133 LPALGETSOURCEI palGetSourcei = NULL;
134 LPALGETSOURCE3I palGetSource3i = NULL;
135 LPALGETSOURCEIV palGetSourceiv = NULL;
136 LPALSOURCEPLAYV palSourcePlayv = NULL;
137 LPALSOURCESTOPV palSourceStopv = NULL;
138 LPALSOURCEREWINDV palSourceRewindv = NULL;
139 LPALSOURCEPAUSEV palSourcePausev = NULL;
140 LPALSOURCEPLAY palSourcePlay = NULL;
141 LPALSOURCESTOP palSourceStop = NULL;
142 LPALSOURCEREWIND palSourceRewind = NULL;
143 LPALSOURCEPAUSE palSourcePause = NULL;
144 LPALSOURCEQUEUEBUFFERS palSourceQueueBuffers = NULL;
145 LPALSOURCEUNQUEUEBUFFERS palSourceUnqueueBuffers = NULL;
146 LPALGENBUFFERS palGenBuffers = NULL;
147 LPALDELETEBUFFERS palDeleteBuffers = NULL;
148 LPALISBUFFER palIsBuffer = NULL;
149 LPALBUFFERF palBufferf = NULL;
150 LPALBUFFER3F palBuffer3f = NULL;
151 LPALBUFFERFV palBufferfv = NULL;
152 LPALBUFFERI palBufferi = NULL;
153 LPALBUFFER3I palBuffer3i = NULL;
154 LPALBUFFERIV palBufferiv = NULL;
155 LPALGETBUFFERF palGetBufferf = NULL;
156 LPALGETBUFFER3F palGetBuffer3f = NULL;
157 LPALGETBUFFERFV palGetBufferfv = NULL;
158 LPALGETBUFFERI palGetBufferi = NULL;
159 LPALGETBUFFER3I palGetBuffer3i = NULL;
160 LPALGETBUFFERIV palGetBufferiv = NULL;
161 LPALBUFFERDATA palBufferData = NULL;
162 LPALDOPPLERFACTOR palDopplerFactor = NULL;
163 LPALDOPPLERVELOCITY palDopplerVelocity = NULL;
164 LPALDISTANCEMODEL palDistanceModel = NULL;
165 LPALSPEEDOFSOUND palSpeedOfSound = NULL;
166 #endif
167
168 typeof(alcGetCurrentContext) *get_context;
169 typeof(alcMakeContextCurrent) *set_context;
170
171 static void load_libopenal(void)
172 {
173     DWORD failed = 0;
174
175 #ifdef SONAME_LIBOPENAL
176     char error[128];
177     openal_handle = wine_dlopen(SONAME_LIBOPENAL, RTLD_NOW, error, sizeof(error));
178     if (!openal_handle)
179     {
180         ERR("Couldn't load " SONAME_LIBOPENAL ": %s\n", error);
181         return;
182     }
183
184 #define LOAD_FUNCPTR(f) \
185     if((p##f = wine_dlsym(openal_handle, #f, NULL, 0)) == NULL) { \
186         ERR("Couldn't lookup %s in libopenal\n", #f); \
187         failed = 1; \
188     }
189
190     LOAD_FUNCPTR(alcCreateContext);
191     LOAD_FUNCPTR(alcMakeContextCurrent);
192     LOAD_FUNCPTR(alcProcessContext);
193     LOAD_FUNCPTR(alcSuspendContext);
194     LOAD_FUNCPTR(alcDestroyContext);
195     LOAD_FUNCPTR(alcGetCurrentContext);
196     LOAD_FUNCPTR(alcGetContextsDevice);
197     LOAD_FUNCPTR(alcOpenDevice);
198     LOAD_FUNCPTR(alcCloseDevice);
199     LOAD_FUNCPTR(alcGetError);
200     LOAD_FUNCPTR(alcIsExtensionPresent);
201     LOAD_FUNCPTR(alcGetProcAddress);
202     LOAD_FUNCPTR(alcGetEnumValue);
203     LOAD_FUNCPTR(alcGetString);
204     LOAD_FUNCPTR(alcGetIntegerv);
205     LOAD_FUNCPTR(alcCaptureOpenDevice);
206     LOAD_FUNCPTR(alcCaptureCloseDevice);
207     LOAD_FUNCPTR(alcCaptureStart);
208     LOAD_FUNCPTR(alcCaptureStop);
209     LOAD_FUNCPTR(alcCaptureSamples);
210     LOAD_FUNCPTR(alEnable);
211     LOAD_FUNCPTR(alDisable);
212     LOAD_FUNCPTR(alIsEnabled);
213     LOAD_FUNCPTR(alGetString);
214     LOAD_FUNCPTR(alGetBooleanv);
215     LOAD_FUNCPTR(alGetIntegerv);
216     LOAD_FUNCPTR(alGetFloatv);
217     LOAD_FUNCPTR(alGetDoublev);
218     LOAD_FUNCPTR(alGetBoolean);
219     LOAD_FUNCPTR(alGetInteger);
220     LOAD_FUNCPTR(alGetFloat);
221     LOAD_FUNCPTR(alGetDouble);
222     LOAD_FUNCPTR(alGetError);
223     LOAD_FUNCPTR(alIsExtensionPresent);
224     LOAD_FUNCPTR(alGetProcAddress);
225     LOAD_FUNCPTR(alGetEnumValue);
226     LOAD_FUNCPTR(alListenerf);
227     LOAD_FUNCPTR(alListener3f);
228     LOAD_FUNCPTR(alListenerfv);
229     LOAD_FUNCPTR(alListeneri);
230     LOAD_FUNCPTR(alListener3i);
231     LOAD_FUNCPTR(alListeneriv);
232     LOAD_FUNCPTR(alGetListenerf);
233     LOAD_FUNCPTR(alGetListener3f);
234     LOAD_FUNCPTR(alGetListenerfv);
235     LOAD_FUNCPTR(alGetListeneri);
236     LOAD_FUNCPTR(alGetListener3i);
237     LOAD_FUNCPTR(alGetListeneriv);
238     LOAD_FUNCPTR(alGenSources);
239     LOAD_FUNCPTR(alDeleteSources);
240     LOAD_FUNCPTR(alIsSource);
241     LOAD_FUNCPTR(alSourcef);
242     LOAD_FUNCPTR(alSource3f);
243     LOAD_FUNCPTR(alSourcefv);
244     LOAD_FUNCPTR(alSourcei);
245     LOAD_FUNCPTR(alSource3i);
246     LOAD_FUNCPTR(alSourceiv);
247     LOAD_FUNCPTR(alGetSourcef);
248     LOAD_FUNCPTR(alGetSource3f);
249     LOAD_FUNCPTR(alGetSourcefv);
250     LOAD_FUNCPTR(alGetSourcei);
251     LOAD_FUNCPTR(alGetSource3i);
252     LOAD_FUNCPTR(alGetSourceiv);
253     LOAD_FUNCPTR(alSourcePlayv);
254     LOAD_FUNCPTR(alSourceStopv);
255     LOAD_FUNCPTR(alSourceRewindv);
256     LOAD_FUNCPTR(alSourcePausev);
257     LOAD_FUNCPTR(alSourcePlay);
258     LOAD_FUNCPTR(alSourceStop);
259     LOAD_FUNCPTR(alSourceRewind);
260     LOAD_FUNCPTR(alSourcePause);
261     LOAD_FUNCPTR(alSourceQueueBuffers);
262     LOAD_FUNCPTR(alSourceUnqueueBuffers);
263     LOAD_FUNCPTR(alGenBuffers);
264     LOAD_FUNCPTR(alDeleteBuffers);
265     LOAD_FUNCPTR(alIsBuffer);
266     LOAD_FUNCPTR(alBufferf);
267     LOAD_FUNCPTR(alBuffer3f);
268     LOAD_FUNCPTR(alBufferfv);
269     LOAD_FUNCPTR(alBufferi);
270     LOAD_FUNCPTR(alBuffer3i);
271     LOAD_FUNCPTR(alBufferiv);
272     LOAD_FUNCPTR(alGetBufferf);
273     LOAD_FUNCPTR(alGetBuffer3f);
274     LOAD_FUNCPTR(alGetBufferfv);
275     LOAD_FUNCPTR(alGetBufferi);
276     LOAD_FUNCPTR(alGetBuffer3i);
277     LOAD_FUNCPTR(alGetBufferiv);
278     LOAD_FUNCPTR(alBufferData);
279     LOAD_FUNCPTR(alDopplerFactor);
280     LOAD_FUNCPTR(alDopplerVelocity);
281     LOAD_FUNCPTR(alDistanceModel);
282     LOAD_FUNCPTR(alSpeedOfSound);
283 #undef LOAD_FUNCPTR
284 #endif
285
286     if (failed)
287     {
288         WARN("Unloading openal\n");
289         if (openal_handle != RTLD_DEFAULT)
290             wine_dlclose(openal_handle, NULL, 0);
291         openal_handle = NULL;
292         openal_loaded = 0;
293     }
294     else
295     {
296         openal_loaded = 1;
297         local_contexts = palcIsExtensionPresent(NULL, "ALC_EXT_thread_local_context");
298         if (local_contexts)
299         {
300             set_context = palcGetProcAddress(NULL, "alcSetThreadContext");
301             get_context = palcGetProcAddress(NULL, "alcGetThreadContext");
302             if (!set_context || !get_context)
303             {
304                 ERR("TLS advertised but functions not found, disabling thread local context\n");
305                 local_contexts = 0;
306             }
307         }
308         if (!local_contexts)
309         {
310             set_context = palcMakeContextCurrent;
311             get_context = palcGetCurrentContext;
312         }
313     }
314 }
315
316 #endif /*HAVE_OPENAL*/
317
318 static HINSTANCE instance;
319
320 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
321 {
322     TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
323
324     switch (fdwReason)
325     {
326         case DLL_PROCESS_ATTACH:
327             instance = hinstDLL;
328             DisableThreadLibraryCalls(hinstDLL);
329 #ifdef HAVE_OPENAL
330             load_libopenal();
331 #endif /*HAVE_OPENAL*/
332             break;
333         case DLL_PROCESS_DETACH:
334             MMDevEnum_Free();
335             break;
336     }
337
338     return TRUE;
339 }
340
341 HRESULT WINAPI DllCanUnloadNow(void)
342 {
343     return S_FALSE;
344 }
345
346 typedef HRESULT (*FnCreateInstance)(REFIID riid, LPVOID *ppobj);
347
348 typedef struct {
349     IClassFactory IClassFactory_iface;
350     REFCLSID rclsid;
351     FnCreateInstance pfnCreateInstance;
352 } IClassFactoryImpl;
353
354 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
355 {
356     return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
357 }
358
359 static HRESULT WINAPI
360 MMCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppobj)
361 {
362     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
363     TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
364     if (ppobj == NULL)
365         return E_POINTER;
366     if (IsEqualIID(riid, &IID_IUnknown) ||
367         IsEqualIID(riid, &IID_IClassFactory))
368     {
369         *ppobj = iface;
370         IUnknown_AddRef(iface);
371         return S_OK;
372     }
373     *ppobj = NULL;
374     return E_NOINTERFACE;
375 }
376
377 static ULONG WINAPI MMCF_AddRef(LPCLASSFACTORY iface)
378 {
379     return 2;
380 }
381
382 static ULONG WINAPI MMCF_Release(LPCLASSFACTORY iface)
383 {
384     /* static class, won't be freed */
385     return 1;
386 }
387
388 static HRESULT WINAPI MMCF_CreateInstance(
389     LPCLASSFACTORY iface,
390     LPUNKNOWN pOuter,
391     REFIID riid,
392     LPVOID *ppobj)
393 {
394     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
395     TRACE("(%p, %p, %s, %p)\n", This, pOuter, debugstr_guid(riid), ppobj);
396
397     if (pOuter)
398         return CLASS_E_NOAGGREGATION;
399
400     if (ppobj == NULL) {
401         WARN("invalid parameter\n");
402         return E_POINTER;
403     }
404     *ppobj = NULL;
405     return This->pfnCreateInstance(riid, ppobj);
406 }
407
408 static HRESULT WINAPI MMCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
409 {
410     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
411     FIXME("(%p, %d) stub!\n", This, dolock);
412     return S_OK;
413 }
414
415 static const IClassFactoryVtbl MMCF_Vtbl = {
416     MMCF_QueryInterface,
417     MMCF_AddRef,
418     MMCF_Release,
419     MMCF_CreateInstance,
420     MMCF_LockServer
421 };
422
423 static IClassFactoryImpl MMDEVAPI_CF[] = {
424     { { &MMCF_Vtbl }, &CLSID_MMDeviceEnumerator, (FnCreateInstance)MMDevEnum_Create }
425 };
426
427 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
428 {
429     int i = 0;
430     TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
431
432     if (ppv == NULL) {
433         WARN("invalid parameter\n");
434         return E_INVALIDARG;
435     }
436
437     *ppv = NULL;
438
439     if (!IsEqualIID(riid, &IID_IClassFactory) &&
440         !IsEqualIID(riid, &IID_IUnknown)) {
441         WARN("no interface for %s\n", debugstr_guid(riid));
442         return E_NOINTERFACE;
443     }
444
445     for (i = 0; i < sizeof(MMDEVAPI_CF)/sizeof(MMDEVAPI_CF[0]); ++i)
446     {
447         if (IsEqualGUID(rclsid, MMDEVAPI_CF[i].rclsid)) {
448             IUnknown_AddRef(&MMDEVAPI_CF[i].IClassFactory_iface);
449             *ppv = &MMDEVAPI_CF[i];
450             return S_OK;
451         }
452         i++;
453     }
454
455     WARN("(%s, %s, %p): no class found.\n", debugstr_guid(rclsid),
456          debugstr_guid(riid), ppv);
457     return CLASS_E_CLASSNOTAVAILABLE;
458 }
459
460 /***********************************************************************
461  *              DllRegisterServer (MMDEVAPI.@)
462  */
463 HRESULT WINAPI DllRegisterServer(void)
464 {
465     return __wine_register_resources( instance, NULL );
466 }
467
468 /***********************************************************************
469  *              DllUnregisterServer (MMDEVAPI.@)
470  */
471 HRESULT WINAPI DllUnregisterServer(void)
472 {
473     return __wine_unregister_resources( instance, NULL );
474 }