Make sure to handle the right interface when creating the DSound object
[dsound-openal.git] / dsound8.c
blob7cdb8bab71965a8c69fd4b07c9ad2e3643999161
1 /* DirectSound COM interface
3 * Copyright 2009 Maarten Lankhorst
5 * Some code taken from the original dsound-openal implementation
6 * Copyright 2007-2009 Chris Robinson
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <stdarg.h>
25 #ifdef __WINESRC__
27 #define COBJMACROS
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "winnls.h"
34 #include "winreg.h"
35 #include "mmsystem.h"
36 #include "winternl.h"
37 #include "mmddk.h"
38 #include "wine/debug.h"
39 #include "dsound.h"
41 #include "dsound_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
45 #else
47 #define WINVER 0x0600
48 #include <windows.h>
49 #include <dsound.h>
51 #include "dsound_private.h"
53 #ifndef DSSPEAKER_7POINT1
54 #define DSSPEAKER_7POINT1 7
55 #endif
57 #endif
59 static DS8Impl **devicelist;
60 static UINT devicelistsize;
62 static const IDirectSound8Vtbl DS8_Vtbl;
64 static inline DS8Impl *impl_from_IDirectSound8(IDirectSound8 *iface)
66 return CONTAINING_RECORD(iface, DS8Impl, IDirectSound8_iface);
69 HRESULT DSOUND_Create(REFIID riid, void **ds)
71 HRESULT hr;
73 if(IsEqualIID(riid, &IID_IDirectSound8))
74 return E_NOINTERFACE;
75 hr = DSOUND_Create8(&IID_IDirectSound8, ds);
76 if(hr == S_OK)
78 DS8Impl *impl = impl_from_IDirectSound8(*ds);
79 impl->is_8 = FALSE;
81 hr = IDirectSound8_QueryInterface(&impl->IDirectSound8_iface, riid, ds);
82 IDirectSound8_Release(&impl->IDirectSound8_iface);
84 return hr;
87 static void DS8Impl_Destroy(DS8Impl *This);
89 static const WCHAR speakerconfigkey[] = {
90 'S','Y','S','T','E','M','\\',
91 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
92 'C','o','n','t','r','o','l','\\',
93 'M','e','d','i','a','R','e','s','o','u','r','c','e','s','\\',
94 'D','i','r','e','c','t','S','o','u','n','d','\\',
95 'S','p','e','a','k','e','r',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',0
98 static const WCHAR speakerconfig[] = {
99 'S','p','e','a','k','e','r',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',0
102 HRESULT DSOUND_Create8(REFIID riid, LPVOID *ds)
104 DS8Impl *This;
105 HKEY regkey;
106 HRESULT hr;
108 *ds = NULL;
109 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
110 if(!This)
111 return E_OUTOFMEMORY;
112 This->IDirectSound8_iface.lpVtbl = (IDirectSound8Vtbl*)&DS8_Vtbl;
114 This->is_8 = TRUE;
115 This->speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, DSSPEAKER_GEOMETRY_WIDE);
117 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, speakerconfigkey, 0, KEY_READ, &regkey) == ERROR_SUCCESS)
119 DWORD type, conf, confsize = sizeof(DWORD);
121 if(RegQueryValueExW(regkey, speakerconfig, NULL, &type, (BYTE*)&conf, &confsize) == ERROR_SUCCESS)
123 if(type == REG_DWORD)
124 This->speaker_config = conf;
127 RegCloseKey(regkey);
129 /*RegGetValueW(HKEY_LOCAL_MACHINE, speakerconfigkey, speakerconfig, RRF_RT_REG_DWORD, NULL, &This->speaker_config, NULL);*/
131 hr = IDirectSound8_QueryInterface(&This->IDirectSound8_iface, riid, ds);
132 if(FAILED(hr))
133 DS8Impl_Destroy(This);
134 else
136 void *temp;
138 EnterCriticalSection(&openal_crst);
139 if(devicelist)
140 temp = HeapReAlloc(GetProcessHeap(), 0, devicelist, sizeof(*devicelist)*(devicelistsize+1));
141 else
142 temp = HeapAlloc(GetProcessHeap(), 0, sizeof(*devicelist)*(devicelistsize+1));
143 if(temp)
145 devicelist = temp;
146 devicelist[devicelistsize++] = This;
148 LeaveCriticalSection(&openal_crst);
150 return hr;
153 static void DS8Impl_Destroy(DS8Impl *This)
155 UINT i;
157 EnterCriticalSection(&openal_crst);
158 for(i = 0;i < devicelistsize;i++)
160 if(devicelist[i] == This)
162 devicelist[i] = devicelist[--devicelistsize];
163 if(devicelistsize == 0)
165 HeapFree(GetProcessHeap(), 0, devicelist);
166 devicelist = NULL;
168 break;
171 LeaveCriticalSection(&openal_crst);
173 if(This->deviceref && InterlockedDecrement(This->deviceref) == 0)
175 if(This->primary)
176 DS8Primary_Destroy(This->primary);
177 if(This->device)
178 alcCloseDevice(This->device);
180 HeapFree(GetProcessHeap(), 0, This->deviceref);
182 else
184 EnterCriticalSection(&openal_crst);
185 if(This->primary && This->primary->parent == This)
187 /* If the primary is referencing this as its parent, update it to
188 * reference another handle for the device */
189 for(i = 0;i < devicelistsize;i++)
191 if(devicelist[i]->primary == This->primary)
193 This->primary->parent = devicelist[i];
194 break;
198 LeaveCriticalSection(&openal_crst);
201 HeapFree(GetProcessHeap(), 0, This);
205 static HRESULT WINAPI DS8_QueryInterface(IDirectSound8 *iface, REFIID riid, LPVOID *ppv)
207 DS8Impl *This = impl_from_IDirectSound8(iface);
209 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
211 *ppv = NULL;
212 if(IsEqualIID(riid, &IID_IUnknown) ||
213 IsEqualIID(riid, &IID_IDirectSound))
214 *ppv = &This->IDirectSound8_iface;
215 else if((IsEqualIID(riid, &IID_IDirectSound8)))
217 if(This->is_8)
218 *ppv = &This->IDirectSound8_iface;
220 else
221 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid));
223 if(*ppv)
225 IUnknown_AddRef((IUnknown*)*ppv);
226 return S_OK;
229 return E_NOINTERFACE;
232 static ULONG WINAPI DS8_AddRef(IDirectSound8 *iface)
234 DS8Impl *This = impl_from_IDirectSound8(iface);
235 LONG ref;
237 ref = InterlockedIncrement(&This->ref);
238 TRACE("Reference count incremented to %d\n", ref);
240 return ref;
243 static ULONG WINAPI DS8_Release(IDirectSound8 *iface)
245 DS8Impl *This = impl_from_IDirectSound8(iface);
246 LONG ref;
248 ref = InterlockedDecrement(&This->ref);
249 TRACE("Reference count decremented to %d\n", ref);
250 if(ref == 0)
251 DS8Impl_Destroy(This);
253 return ref;
256 static HRESULT WINAPI DS8_CreateSoundBuffer(IDirectSound8 *iface, LPCDSBUFFERDESC desc, LPLPDIRECTSOUNDBUFFER buf, IUnknown *pUnkOuter)
258 DS8Impl *This = impl_from_IDirectSound8(iface);
259 HRESULT hr;
261 TRACE("(%p)->(%p, %p, %p)\n", iface, desc, buf, pUnkOuter);
263 if(!buf)
265 WARN("buf is null\n");
266 return DSERR_INVALIDPARAM;
268 *buf = NULL;
270 if(pUnkOuter)
272 WARN("Aggregation isn't supported\n");
273 return DSERR_NOAGGREGATION;
275 if(!desc || desc->dwSize < sizeof(DSBUFFERDESC1))
277 WARN("Invalid buffer %p/%u\n", desc, desc?desc->dwSize:0);
278 return DSERR_INVALIDPARAM;
281 if(!This->primary)
283 WARN("Device not initialized\n");
284 return DSERR_UNINITIALIZED;
287 TRACE("Requested buffer:\n"
288 " Size = %u\n"
289 " Flags = 0x%08x\n"
290 " BufferBytes = %u\n",
291 (UINT)desc->dwSize, (UINT)desc->dwFlags,
292 (UINT)desc->dwBufferBytes);
294 if(desc->dwSize >= sizeof(DSBUFFERDESC))
296 if(!(desc->dwFlags&DSBCAPS_CTRL3D))
298 if(!IsEqualGUID(&desc->guid3DAlgorithm, &GUID_NULL))
300 WARN("Invalid 3D algorithm GUID specified for non-3D buffer: %s\n", debugstr_guid(&desc->guid3DAlgorithm));
301 return DSERR_INVALIDPARAM;
304 else
305 TRACE("Requested 3D algorithm GUID: %s\n", debugstr_guid(&desc->guid3DAlgorithm));
308 /* OpenAL doesn't support playing with 3d and panning at same time.. */
309 if((desc->dwFlags&(DSBCAPS_CTRL3D|DSBCAPS_CTRLPAN)) == (DSBCAPS_CTRL3D|DSBCAPS_CTRLPAN))
311 if(!This->is_8)
312 ERR("Cannot create buffers with 3D and panning control\n");
313 else
314 WARN("Cannot create buffers with 3D and panning control\n");
315 return DSERR_INVALIDPARAM;
318 EnterCriticalSection(&This->primary->crst);
319 if((desc->dwFlags&DSBCAPS_PRIMARYBUFFER))
321 IDirectSoundBuffer *prim = &This->primary->IDirectSoundBuffer_iface;
323 hr = S_OK;
324 if(IDirectSoundBuffer_AddRef(prim) == 1)
326 hr = IDirectSoundBuffer_Initialize(prim, (IDirectSound*)&This->IDirectSound8_iface, desc);
327 if(FAILED(hr))
329 IDirectSoundBuffer_Release(prim);
330 prim = NULL;
333 *buf = prim;
335 else
337 DS8Buffer *dsb;
339 hr = DS8Buffer_Create(&dsb, This->primary, NULL);
340 if(SUCCEEDED(hr))
342 hr = IDirectSoundBuffer8_Initialize(&dsb->IDirectSoundBuffer8_iface, (IDirectSound*)&This->IDirectSound8_iface, desc);
343 if(FAILED(hr))
344 IDirectSoundBuffer8_Release(&dsb->IDirectSoundBuffer8_iface);
345 else
347 dsb->bufferlost = (This->prio_level == DSSCL_WRITEPRIMARY);
348 *buf = &dsb->IDirectSoundBuffer_iface;
352 LeaveCriticalSection(&This->primary->crst);
354 TRACE("%08x\n", hr);
355 return hr;
358 static HRESULT WINAPI DS8_GetCaps(IDirectSound8 *iface, LPDSCAPS caps)
360 DS8Impl *This = impl_from_IDirectSound8(iface);
361 LONG count;
363 TRACE("(%p)->(%p)\n", iface, caps);
365 if(!This->primary)
367 WARN("Device not initialized\n");
368 return DSERR_UNINITIALIZED;
371 if(!caps || caps->dwSize < sizeof(*caps))
373 WARN("Invalid DSCAPS (%p, %u)\n", caps, (caps?caps->dwSize:0));
374 return DSERR_INVALIDPARAM;
377 EnterCriticalSection(&This->primary->crst);
378 count = This->primary->max_sources;
380 setALContext(This->primary->ctx);
381 caps->dwFlags = DSCAPS_CONTINUOUSRATE |
382 DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO |
383 DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYMONO |
384 DSCAPS_SECONDARY16BIT | DSCAPS_SECONDARY8BIT |
385 DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
386 caps->dwPrimaryBuffers = 1;
387 caps->dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
388 caps->dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
389 caps->dwMaxHwMixingAllBuffers =
390 caps->dwMaxHwMixingStaticBuffers =
391 caps->dwMaxHwMixingStreamingBuffers =
392 caps->dwMaxHw3DAllBuffers =
393 caps->dwMaxHw3DStaticBuffers =
394 caps->dwMaxHw3DStreamingBuffers = count;
395 count -= This->primary->nbuffers;
396 if(count < 0)
398 ERR("How did the count drop below 0?\n");
399 count = 0;
401 caps->dwFreeHwMixingAllBuffers =
402 caps->dwFreeHwMixingStaticBuffers =
403 caps->dwFreeHwMixingStreamingBuffers =
404 caps->dwFreeHw3DAllBuffers =
405 caps->dwFreeHw3DStaticBuffers =
406 caps->dwFreeHw3DStreamingBuffers = count;
407 caps->dwTotalHwMemBytes =
408 caps->dwFreeHwMemBytes = 64 * 1024 * 1024;
409 caps->dwMaxContigFreeHwMemBytes = caps->dwFreeHwMemBytes;
410 caps->dwUnlockTransferRateHwBuffers = 4096;
411 caps->dwPlayCpuOverheadSwBuffers = 0;
412 popALContext();
414 LeaveCriticalSection(&This->primary->crst);
416 return DS_OK;
418 static HRESULT WINAPI DS8_DuplicateSoundBuffer(IDirectSound8 *iface, IDirectSoundBuffer *in, IDirectSoundBuffer **out)
420 DS8Impl *This = impl_from_IDirectSound8(iface);
421 DS8Buffer *buf;
422 DSBCAPS caps;
423 HRESULT hr;
425 TRACE("(%p)->(%p, %p)\n", iface, in, out);
427 if(!This->primary)
429 WARN("Device not initialized\n");
430 return DSERR_UNINITIALIZED;
433 if(!in || !out)
435 WARN("Invalid pointer: int = %p, out = %p\n", in, out);
436 return DSERR_INVALIDPARAM;
438 *out = NULL;
440 EnterCriticalSection(&This->primary->crst);
442 caps.dwSize = sizeof(caps);
443 hr = IDirectSoundBuffer_GetCaps(in, &caps);
444 if(SUCCEEDED(hr) && (caps.dwFlags&DSBCAPS_PRIMARYBUFFER))
446 WARN("Cannot duplicate buffer %p, which has DSBCAPS_PRIMARYBUFFER\n", in);
447 hr = DSERR_INVALIDPARAM;
449 if(SUCCEEDED(hr) && (caps.dwFlags&DSBCAPS_CTRLFX))
451 WARN("Cannot duplicate buffer %p, which has DSBCAPS_CTRLFX\n", in);
452 hr = DSERR_INVALIDPARAM;
454 if(SUCCEEDED(hr))
455 hr = DS8Buffer_Create(&buf, This->primary, in);
456 if(SUCCEEDED(hr))
458 *out = &buf->IDirectSoundBuffer_iface;
459 hr = IDirectSoundBuffer_Initialize(*out, NULL, NULL);
461 if(SUCCEEDED(hr))
463 /* According to MSDN volume isn't copied */
464 if((caps.dwFlags&DSBCAPS_CTRLPAN))
466 LONG pan;
467 if(SUCCEEDED(IDirectSoundBuffer_GetPan(in, &pan)))
468 IDirectSoundBuffer_SetPan(*out, pan);
470 if((caps.dwFlags&DSBCAPS_CTRLFREQUENCY))
472 DWORD freq;
473 if(SUCCEEDED(IDirectSoundBuffer_GetFrequency(in, &freq)))
474 IDirectSoundBuffer_SetFrequency(*out, freq);
476 if((caps.dwFlags&DSBCAPS_CTRL3D))
478 IDirectSound3DBuffer *buf3d;
479 DS3DBUFFER DS3DBuffer;
480 HRESULT subhr;
482 subhr = IDirectSound_QueryInterface(in, &IID_IDirectSound3DBuffer, (void**)&buf3d);
483 if(SUCCEEDED(subhr))
485 DS3DBuffer.dwSize = sizeof(DS3DBuffer);
486 subhr = IDirectSound3DBuffer_GetAllParameters(buf3d, &DS3DBuffer);
487 IDirectSound3DBuffer_Release(buf3d);
489 if(SUCCEEDED(subhr))
490 subhr = IDirectSoundBuffer_QueryInterface(*out, &IID_IDirectSound3DBuffer, (void**)&buf3d);
491 if(SUCCEEDED(subhr))
493 subhr = IDirectSound3DBuffer_SetAllParameters(buf3d, &DS3DBuffer, DS3D_IMMEDIATE);
494 IDirectSound3DBuffer_Release(buf3d);
498 if(FAILED(hr))
500 if(*out)
501 IDirectSoundBuffer_Release(*out);
502 *out = NULL;
505 LeaveCriticalSection(&This->primary->crst);
506 return hr;
509 static HRESULT WINAPI DS8_SetCooperativeLevel(IDirectSound8 *iface, HWND hwnd, DWORD level)
511 DS8Impl *This = impl_from_IDirectSound8(iface);
512 HRESULT hr = S_OK;
514 TRACE("(%p)->(%p, %u)\n", iface, hwnd, level);
516 if(!This->primary)
518 WARN("Device not initialized\n");
519 return DSERR_UNINITIALIZED;
522 if(level > DSSCL_WRITEPRIMARY || level < DSSCL_NORMAL)
524 WARN("Invalid coop level: %u\n", level);
525 return DSERR_INVALIDPARAM;
528 EnterCriticalSection(&This->primary->crst);
529 if(level == DSSCL_WRITEPRIMARY && (This->prio_level != DSSCL_WRITEPRIMARY))
531 DWORD i, state;
533 for(i = 0; i < This->primary->nbuffers; ++i)
535 DS8Buffer *buf = This->primary->buffers[i];
536 if(FAILED(IDirectSoundBuffer_GetStatus(&buf->IDirectSoundBuffer8_iface, &state)) ||
537 (state&DSBSTATUS_PLAYING))
539 WARN("DSSCL_WRITEPRIMARY set with playing buffers!\n");
540 hr = DSERR_INVALIDCALL;
541 goto out;
543 /* Mark buffer as lost */
544 buf->bufferlost = 1;
546 if(This->primary->write_emu)
548 ERR("Why was there a write_emu?\n");
549 /* Delete it */
550 IDirectSoundBuffer8_Release(This->primary->write_emu);
551 This->primary->write_emu = NULL;
553 if(This->primary->flags)
555 /* Primary has open references.. create write_emu */
556 DSBUFFERDESC desc;
557 DS8Buffer *emu;
559 memset(&desc, 0, sizeof(desc));
560 desc.dwSize = sizeof(desc);
561 desc.dwFlags = DSBCAPS_LOCHARDWARE | (This->primary->flags&DSBCAPS_CTRLPAN);
562 desc.dwBufferBytes = This->primary->buf_size;
563 desc.lpwfxFormat = &This->primary->format.Format;
565 hr = DS8Buffer_Create(&emu, This->primary, NULL);
566 if(SUCCEEDED(hr))
568 This->primary->write_emu = &emu->IDirectSoundBuffer8_iface;
569 hr = IDirectSoundBuffer8_Initialize(This->primary->write_emu, (IDirectSound*)&This->IDirectSound8_iface, &desc);
570 if(FAILED(hr))
572 IDirectSoundBuffer8_Release(This->primary->write_emu);
573 This->primary->write_emu = NULL;
578 else if(This->prio_level == DSSCL_WRITEPRIMARY && level != DSSCL_WRITEPRIMARY && This->primary->write_emu)
580 TRACE("Nuking write_emu\n");
581 /* Delete it */
582 IDirectSoundBuffer8_Release(This->primary->write_emu);
583 This->primary->write_emu = NULL;
585 if(SUCCEEDED(hr))
586 This->prio_level = level;
587 out:
588 LeaveCriticalSection(&This->primary->crst);
590 return hr;
593 static HRESULT WINAPI DS8_Compact(IDirectSound8 *iface)
595 DS8Impl *This = impl_from_IDirectSound8(iface);
596 HRESULT hr = S_OK;
598 TRACE("(%p)->()\n", iface);
600 if(!This->primary)
602 WARN("Device not initialized\n");
603 return DSERR_UNINITIALIZED;
606 EnterCriticalSection(&This->primary->crst);
607 if(This->prio_level < DSSCL_PRIORITY)
609 WARN("Coop level not high enough (%u)\n", This->prio_level);
610 hr = DSERR_PRIOLEVELNEEDED;
612 LeaveCriticalSection(&This->primary->crst);
614 return hr;
617 static HRESULT WINAPI DS8_GetSpeakerConfig(IDirectSound8 *iface, DWORD *config)
619 DS8Impl *This = impl_from_IDirectSound8(iface);
620 HRESULT hr = S_OK;
622 TRACE("(%p)->(%p)\n", iface, config);
624 if(!config)
625 return DSERR_INVALIDPARAM;
626 *config = 0;
628 if(!This->primary)
630 WARN("Device not initialized\n");
631 return DSERR_UNINITIALIZED;
634 EnterCriticalSection(&This->primary->crst);
635 *config = This->speaker_config;
636 LeaveCriticalSection(&This->primary->crst);
638 return hr;
641 static HRESULT WINAPI DS8_SetSpeakerConfig(IDirectSound8 *iface, DWORD config)
643 DS8Impl *This = impl_from_IDirectSound8(iface);
644 DWORD geo, speaker;
645 HKEY key;
646 HRESULT hr;
648 TRACE("(%p)->(0x%08x)\n", iface, config);
650 if(!This->primary)
652 WARN("Device not initialized\n");
653 return DSERR_UNINITIALIZED;
656 EnterCriticalSection(&This->primary->crst);
658 geo = DSSPEAKER_GEOMETRY(config);
659 speaker = DSSPEAKER_CONFIG(config);
661 hr = DSERR_INVALIDPARAM;
662 if(geo && (geo < DSSPEAKER_GEOMETRY_MIN || geo > DSSPEAKER_GEOMETRY_MAX))
664 WARN("Invalid speaker angle %u\n", geo);
665 goto out;
667 if(speaker < DSSPEAKER_HEADPHONE || speaker > DSSPEAKER_7POINT1)
669 WARN("Invalid speaker config %u\n", speaker);
670 goto out;
673 hr = DSERR_GENERIC;
674 if(!RegCreateKeyExW(HKEY_LOCAL_MACHINE, speakerconfigkey, 0, NULL, 0, KEY_WRITE, NULL, &key, NULL))
676 RegSetValueExW(key, speakerconfig, 0, REG_DWORD, (const BYTE*)&config, sizeof(DWORD));
677 This->speaker_config = config;
678 RegCloseKey(key);
679 hr = S_OK;
681 out:
682 LeaveCriticalSection(&This->primary->crst);
684 return hr;
687 static HRESULT WINAPI DS8_Initialize(IDirectSound8 *iface, const GUID *devguid)
689 DS8Impl *This = impl_from_IDirectSound8(iface);
690 const ALCchar *drv_name;
691 HRESULT hr;
692 UINT n;
694 TRACE("(%p)->(%s)\n", iface, debugstr_guid(devguid));
696 if(!openal_loaded)
697 return DSERR_NODRIVER;
699 if(This->primary)
701 WARN("Device already initialized\n");
702 return DSERR_ALREADYINITIALIZED;
705 if(!devguid)
706 devguid = &DSDEVID_DefaultPlayback;
707 hr = GetDeviceID(devguid, &This->guid);
708 if(FAILED(hr))
709 return hr;
711 EnterCriticalSection(&openal_crst);
713 for(n = 0;n < devicelistsize;n++)
715 if(devicelist[n]->device && devicelist[n]->is_8 == This->is_8 &&
716 IsEqualGUID(&devicelist[n]->guid, &This->guid))
718 TRACE("Matched already open device %p\n", devicelist[n]);
720 This->device = devicelist[n]->device;
721 This->primary = devicelist[n]->primary;
722 This->deviceref = devicelist[n]->deviceref;
723 InterlockedIncrement(This->deviceref);
725 hr = DS_OK;
726 goto out;
730 if(!This->deviceref)
732 hr = DSERR_OUTOFMEMORY;
733 if(!(This->deviceref=HeapAlloc(GetProcessHeap(), 0, sizeof(LONG))))
734 goto out;
735 This->deviceref[0] = 1;
738 hr = DSERR_NODRIVER;
739 if(!(drv_name=DSOUND_getdevicestrings()) ||
740 memcmp(&This->guid, &DSOUND_renderer_guid, sizeof(GUID)-1) != 0)
742 WARN("No device found\n");
743 goto out;
746 n = This->guid.Data4[7];
747 while(*drv_name && n--)
748 drv_name += strlen(drv_name) + 1;
749 if(!*drv_name)
751 WARN("No device string found\n");
752 goto out;
755 This->device = alcOpenDevice(drv_name);
756 if(!This->device)
758 alcGetError(NULL);
759 WARN("Couldn't open device \"%s\"\n", drv_name);
760 goto out;
762 TRACE("Opened device: %s\n", alcGetString(This->device, ALC_DEVICE_SPECIFIER));
764 hr = DS8Primary_Create(&This->primary, This);
765 if(FAILED(hr))
767 alcCloseDevice(This->device);
768 This->device = NULL;
771 out:
772 LeaveCriticalSection(&openal_crst);
774 return hr;
777 /* I, Maarten Lankhorst, hereby declare this driver certified
778 * What this means.. ? An extra bit set
780 static HRESULT WINAPI DS8_VerifyCertification(IDirectSound8 *iface, DWORD *certified)
782 DS8Impl *This = impl_from_IDirectSound8(iface);
784 TRACE("(%p)->(%p)\n", iface, certified);
786 if(!certified)
787 return DSERR_INVALIDPARAM;
788 *certified = 0;
790 if(!This->primary)
792 WARN("Device not initialized\n");
793 return DSERR_UNINITIALIZED;
796 *certified = DS_CERTIFIED;
798 return DS_OK;
801 static const IDirectSound8Vtbl DS8_Vtbl =
803 DS8_QueryInterface,
804 DS8_AddRef,
805 DS8_Release,
806 DS8_CreateSoundBuffer,
807 DS8_GetCaps,
808 DS8_DuplicateSoundBuffer,
809 DS8_SetCooperativeLevel,
810 DS8_Compact,
811 DS8_GetSpeakerConfig,
812 DS8_SetSpeakerConfig,
813 DS8_Initialize,
814 DS8_VerifyCertification