Minor cleanup for buffer creation
[dsound-openal.git] / dsound8.c
blobdb4f1c0c894268112c5aef590ed92ebc02156547
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(riid, ds);
76 if(hr == S_OK)
78 DS8Impl *impl = impl_from_IDirectSound8(*ds);
79 impl->is_8 = FALSE;
81 return hr;
84 static void DS8Impl_Destroy(DS8Impl *This);
86 static const WCHAR speakerconfigkey[] = {
87 'S','Y','S','T','E','M','\\',
88 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
89 'C','o','n','t','r','o','l','\\',
90 'M','e','d','i','a','R','e','s','o','u','r','c','e','s','\\',
91 'D','i','r','e','c','t','S','o','u','n','d','\\',
92 'S','p','e','a','k','e','r',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',0
95 static const WCHAR speakerconfig[] = {
96 'S','p','e','a','k','e','r',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',0
99 HRESULT DSOUND_Create8(REFIID riid, LPVOID *ds)
101 DS8Impl *This;
102 HKEY regkey;
103 HRESULT hr;
105 *ds = NULL;
106 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
107 if(!This)
108 return E_OUTOFMEMORY;
109 This->IDirectSound8_iface.lpVtbl = (IDirectSound8Vtbl*)&DS8_Vtbl;
111 This->is_8 = TRUE;
112 This->speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, DSSPEAKER_GEOMETRY_WIDE);
114 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, speakerconfigkey, 0, KEY_READ, &regkey) == ERROR_SUCCESS)
116 DWORD type, conf, confsize = sizeof(DWORD);
118 if(RegQueryValueExW(regkey, speakerconfig, NULL, &type, (BYTE*)&conf, &confsize) == ERROR_SUCCESS)
120 if(type == REG_DWORD)
121 This->speaker_config = conf;
124 RegCloseKey(regkey);
126 /*RegGetValueW(HKEY_LOCAL_MACHINE, speakerconfigkey, speakerconfig, RRF_RT_REG_DWORD, NULL, &This->speaker_config, NULL);*/
128 hr = IDirectSound8_QueryInterface(&This->IDirectSound8_iface, riid, ds);
129 if(FAILED(hr))
130 DS8Impl_Destroy(This);
131 else
133 void *temp;
135 EnterCriticalSection(&openal_crst);
136 if(devicelist)
137 temp = HeapReAlloc(GetProcessHeap(), 0, devicelist, sizeof(*devicelist)*(devicelistsize+1));
138 else
139 temp = HeapAlloc(GetProcessHeap(), 0, sizeof(*devicelist)*(devicelistsize+1));
140 if(temp)
142 devicelist = temp;
143 devicelist[devicelistsize++] = This;
145 LeaveCriticalSection(&openal_crst);
147 return hr;
150 static void DS8Impl_Destroy(DS8Impl *This)
152 UINT i;
154 EnterCriticalSection(&openal_crst);
155 for(i = 0;i < devicelistsize;i++)
157 if(devicelist[i] == This)
159 devicelist[i] = devicelist[--devicelistsize];
160 if(devicelistsize == 0)
162 HeapFree(GetProcessHeap(), 0, devicelist);
163 devicelist = NULL;
165 break;
168 LeaveCriticalSection(&openal_crst);
170 if(This->deviceref && InterlockedDecrement(This->deviceref) == 0)
172 if(This->primary)
173 DS8Primary_Destroy(This->primary);
174 if(This->device)
175 alcCloseDevice(This->device);
177 HeapFree(GetProcessHeap(), 0, This->deviceref);
179 else
181 EnterCriticalSection(&openal_crst);
182 if(This->primary && This->primary->parent == This)
184 /* If the primary is referencing this as its parent, update it to
185 * reference another handle for the device */
186 for(i = 0;i < devicelistsize;i++)
188 if(devicelist[i]->primary == This->primary)
190 This->primary->parent = devicelist[i];
191 break;
195 LeaveCriticalSection(&openal_crst);
198 HeapFree(GetProcessHeap(), 0, This);
202 static HRESULT WINAPI DS8_QueryInterface(IDirectSound8 *iface, REFIID riid, LPVOID *ppv)
204 DS8Impl *This = impl_from_IDirectSound8(iface);
206 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
208 *ppv = NULL;
209 if(IsEqualIID(riid, &IID_IUnknown) ||
210 IsEqualIID(riid, &IID_IDirectSound))
211 *ppv = &This->IDirectSound8_iface;
212 else if((IsEqualIID(riid, &IID_IDirectSound8)))
214 if(This->is_8)
215 *ppv = &This->IDirectSound8_iface;
217 else
218 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid));
220 if(*ppv)
222 IUnknown_AddRef((IUnknown*)*ppv);
223 return S_OK;
226 return E_NOINTERFACE;
229 static ULONG WINAPI DS8_AddRef(IDirectSound8 *iface)
231 DS8Impl *This = impl_from_IDirectSound8(iface);
232 LONG ref;
234 ref = InterlockedIncrement(&This->ref);
235 TRACE("Reference count incremented to %d\n", ref);
237 return ref;
240 static ULONG WINAPI DS8_Release(IDirectSound8 *iface)
242 DS8Impl *This = impl_from_IDirectSound8(iface);
243 LONG ref;
245 ref = InterlockedDecrement(&This->ref);
246 TRACE("Reference count decremented to %d\n", ref);
247 if(ref == 0)
248 DS8Impl_Destroy(This);
250 return ref;
253 static HRESULT WINAPI DS8_CreateSoundBuffer(IDirectSound8 *iface, LPCDSBUFFERDESC desc, LPLPDIRECTSOUNDBUFFER buf, IUnknown *pUnkOuter)
255 DS8Impl *This = impl_from_IDirectSound8(iface);
256 HRESULT hr;
258 TRACE("(%p)->(%p, %p, %p)\n", iface, desc, buf, pUnkOuter);
260 if(!buf)
262 WARN("buf is null\n");
263 return DSERR_INVALIDPARAM;
265 *buf = NULL;
267 if(pUnkOuter)
269 WARN("Aggregation isn't supported\n");
270 return DSERR_NOAGGREGATION;
272 if(!desc || desc->dwSize < sizeof(DSBUFFERDESC1))
274 WARN("Invalid buffer %p/%u\n", desc, desc?desc->dwSize:0);
275 return DSERR_INVALIDPARAM;
278 if(!This->primary)
280 WARN("Device not initialized\n");
281 return DSERR_UNINITIALIZED;
284 TRACE("Requested buffer:\n"
285 " Size = %u\n"
286 " Flags = 0x%08x\n"
287 " BufferBytes = %u\n",
288 (UINT)desc->dwSize, (UINT)desc->dwFlags,
289 (UINT)desc->dwBufferBytes);
291 if(desc->dwSize >= sizeof(DSBUFFERDESC))
293 if(!(desc->dwFlags&DSBCAPS_CTRL3D))
295 if(!IsEqualGUID(&desc->guid3DAlgorithm, &GUID_NULL))
297 WARN("Invalid 3D algorithm GUID specified for non-3D buffer: %s\n", debugstr_guid(&desc->guid3DAlgorithm));
298 return DSERR_INVALIDPARAM;
301 else
302 TRACE("Requested 3D algorithm GUID: %s\n", debugstr_guid(&desc->guid3DAlgorithm));
305 /* OpenAL doesn't support playing with 3d and panning at same time.. */
306 if((desc->dwFlags&(DSBCAPS_CTRL3D|DSBCAPS_CTRLPAN)) == (DSBCAPS_CTRL3D|DSBCAPS_CTRLPAN))
308 if(!This->is_8)
309 ERR("Cannot create buffers with 3D and panning control\n");
310 else
311 WARN("Cannot create buffers with 3D and panning control\n");
312 return DSERR_INVALIDPARAM;
315 EnterCriticalSection(&This->primary->crst);
316 if((desc->dwFlags&DSBCAPS_PRIMARYBUFFER))
318 IDirectSoundBuffer *prim = &This->primary->IDirectSoundBuffer_iface;
320 hr = S_OK;
321 if(IDirectSoundBuffer_AddRef(prim) == 1)
323 hr = IDirectSoundBuffer_Initialize(prim, (IDirectSound*)&This->IDirectSound8_iface, desc);
324 if(FAILED(hr))
326 IDirectSoundBuffer_Release(prim);
327 prim = NULL;
330 *buf = prim;
332 else
334 DS8Buffer *dsb;
336 hr = DS8Buffer_Create(&dsb, This->primary, NULL);
337 if(SUCCEEDED(hr))
339 hr = IDirectSoundBuffer8_Initialize(&dsb->IDirectSoundBuffer8_iface, (IDirectSound*)&This->IDirectSound8_iface, desc);
340 if(FAILED(hr))
341 IDirectSoundBuffer8_Release(&dsb->IDirectSoundBuffer8_iface);
342 else
344 dsb->bufferlost = (This->prio_level == DSSCL_WRITEPRIMARY);
345 *buf = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface;
349 LeaveCriticalSection(&This->primary->crst);
351 TRACE("%08x\n", hr);
352 return hr;
355 static HRESULT WINAPI DS8_GetCaps(IDirectSound8 *iface, LPDSCAPS caps)
357 DS8Impl *This = impl_from_IDirectSound8(iface);
358 LONG count;
360 TRACE("(%p)->(%p)\n", iface, caps);
362 if(!This->primary)
364 WARN("Device not initialized\n");
365 return DSERR_UNINITIALIZED;
368 if(!caps || caps->dwSize < sizeof(*caps))
370 WARN("Invalid DSCAPS (%p, %u)\n", caps, (caps?caps->dwSize:0));
371 return DSERR_INVALIDPARAM;
374 EnterCriticalSection(&This->primary->crst);
375 count = This->primary->max_sources;
377 setALContext(This->primary->ctx);
378 caps->dwFlags = DSCAPS_CONTINUOUSRATE |
379 DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO |
380 DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYMONO |
381 DSCAPS_SECONDARY16BIT | DSCAPS_SECONDARY8BIT |
382 DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
383 caps->dwPrimaryBuffers = 1;
384 caps->dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
385 caps->dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
386 caps->dwMaxHwMixingAllBuffers =
387 caps->dwMaxHwMixingStaticBuffers =
388 caps->dwMaxHwMixingStreamingBuffers =
389 caps->dwMaxHw3DAllBuffers =
390 caps->dwMaxHw3DStaticBuffers =
391 caps->dwMaxHw3DStreamingBuffers = count;
392 count -= This->primary->nbuffers;
393 if(count < 0)
395 ERR("How did the count drop below 0?\n");
396 count = 0;
398 caps->dwFreeHwMixingAllBuffers =
399 caps->dwFreeHwMixingStaticBuffers =
400 caps->dwFreeHwMixingStreamingBuffers =
401 caps->dwFreeHw3DAllBuffers =
402 caps->dwFreeHw3DStaticBuffers =
403 caps->dwFreeHw3DStreamingBuffers = count;
404 caps->dwTotalHwMemBytes =
405 caps->dwFreeHwMemBytes = 64 * 1024 * 1024;
406 caps->dwMaxContigFreeHwMemBytes = caps->dwFreeHwMemBytes;
407 caps->dwUnlockTransferRateHwBuffers = 4096;
408 caps->dwPlayCpuOverheadSwBuffers = 0;
409 popALContext();
411 LeaveCriticalSection(&This->primary->crst);
413 return DS_OK;
415 static HRESULT WINAPI DS8_DuplicateSoundBuffer(IDirectSound8 *iface, IDirectSoundBuffer *in, IDirectSoundBuffer **out)
417 DS8Impl *This = impl_from_IDirectSound8(iface);
418 DS8Buffer *buf;
419 DSBCAPS caps;
420 HRESULT hr;
422 TRACE("(%p)->(%p, %p)\n", iface, in, out);
424 if(!This->primary)
426 WARN("Device not initialized\n");
427 return DSERR_UNINITIALIZED;
430 if(!in || !out)
432 WARN("Invalid pointer: int = %p, out = %p\n", in, out);
433 return DSERR_INVALIDPARAM;
435 *out = NULL;
437 EnterCriticalSection(&This->primary->crst);
439 caps.dwSize = sizeof(caps);
440 hr = IDirectSoundBuffer_GetCaps(in, &caps);
441 if(SUCCEEDED(hr) && (caps.dwFlags&DSBCAPS_PRIMARYBUFFER))
443 WARN("Cannot duplicate buffer %p, which has DSBCAPS_PRIMARYBUFFER\n", in);
444 hr = DSERR_INVALIDPARAM;
446 if(SUCCEEDED(hr) && (caps.dwFlags&DSBCAPS_CTRLFX))
448 WARN("Cannot duplicate buffer %p, which has DSBCAPS_CTRLFX\n", in);
449 hr = DSERR_INVALIDPARAM;
451 if(SUCCEEDED(hr))
452 hr = DS8Buffer_Create(&buf, This->primary, in);
453 if(SUCCEEDED(hr))
455 *out = (IDirectSoundBuffer*)&buf->IDirectSoundBuffer8_iface;
456 hr = IDirectSoundBuffer_Initialize(*out, NULL, NULL);
458 if(SUCCEEDED(hr))
460 /* According to MSDN volume isn't copied */
461 if((caps.dwFlags&DSBCAPS_CTRLPAN))
463 LONG pan;
464 if(SUCCEEDED(IDirectSoundBuffer_GetPan(in, &pan)))
465 IDirectSoundBuffer_SetPan(*out, pan);
467 if((caps.dwFlags&DSBCAPS_CTRLFREQUENCY))
469 DWORD freq;
470 if(SUCCEEDED(IDirectSoundBuffer_GetFrequency(in, &freq)))
471 IDirectSoundBuffer_SetFrequency(*out, freq);
473 if((caps.dwFlags&DSBCAPS_CTRL3D))
475 IDirectSound3DBuffer *buf3d;
476 DS3DBUFFER DS3DBuffer;
477 HRESULT subhr;
479 subhr = IDirectSound_QueryInterface(in, &IID_IDirectSound3DBuffer, (void**)&buf3d);
480 if(SUCCEEDED(subhr))
482 DS3DBuffer.dwSize = sizeof(DS3DBuffer);
483 subhr = IDirectSound3DBuffer_GetAllParameters(buf3d, &DS3DBuffer);
484 IDirectSound3DBuffer_Release(buf3d);
486 if(SUCCEEDED(subhr))
487 subhr = IDirectSoundBuffer_QueryInterface(*out, &IID_IDirectSound3DBuffer, (void**)&buf3d);
488 if(SUCCEEDED(subhr))
490 subhr = IDirectSound3DBuffer_SetAllParameters(buf3d, &DS3DBuffer, DS3D_IMMEDIATE);
491 IDirectSound3DBuffer_Release(buf3d);
495 if(FAILED(hr))
497 if(*out)
498 IDirectSoundBuffer_Release(*out);
499 *out = NULL;
502 LeaveCriticalSection(&This->primary->crst);
503 return hr;
506 static HRESULT WINAPI DS8_SetCooperativeLevel(IDirectSound8 *iface, HWND hwnd, DWORD level)
508 DS8Impl *This = impl_from_IDirectSound8(iface);
509 HRESULT hr = S_OK;
511 TRACE("(%p)->(%p, %u)\n", iface, hwnd, level);
513 if(!This->primary)
515 WARN("Device not initialized\n");
516 return DSERR_UNINITIALIZED;
519 if(level > DSSCL_WRITEPRIMARY || level < DSSCL_NORMAL)
521 WARN("Invalid coop level: %u\n", level);
522 return DSERR_INVALIDPARAM;
525 EnterCriticalSection(&This->primary->crst);
526 if(level == DSSCL_WRITEPRIMARY && (This->prio_level != DSSCL_WRITEPRIMARY))
528 DWORD i, state;
530 for(i = 0; i < This->primary->nbuffers; ++i)
532 DS8Buffer *buf = This->primary->buffers[i];
533 if(FAILED(IDirectSoundBuffer_GetStatus(&buf->IDirectSoundBuffer8_iface, &state)) ||
534 (state&DSBSTATUS_PLAYING))
536 WARN("DSSCL_WRITEPRIMARY set with playing buffers!\n");
537 hr = DSERR_INVALIDCALL;
538 goto out;
540 /* Mark buffer as lost */
541 buf->bufferlost = 1;
543 if(This->primary->write_emu)
545 ERR("Why was there a write_emu?\n");
546 /* Delete it */
547 IDirectSoundBuffer8_Release(This->primary->write_emu);
548 This->primary->write_emu = NULL;
550 if(This->primary->flags)
552 /* Primary has open references.. create write_emu */
553 DSBUFFERDESC desc;
554 DS8Buffer *emu;
556 memset(&desc, 0, sizeof(desc));
557 desc.dwSize = sizeof(desc);
558 desc.dwFlags = DSBCAPS_LOCHARDWARE | (This->primary->flags&DSBCAPS_CTRLPAN);
559 desc.dwBufferBytes = This->primary->buf_size;
560 desc.lpwfxFormat = &This->primary->format.Format;
562 hr = DS8Buffer_Create(&emu, This->primary, NULL);
563 if(SUCCEEDED(hr))
565 This->primary->write_emu = &emu->IDirectSoundBuffer8_iface;
566 hr = IDirectSoundBuffer8_Initialize(This->primary->write_emu, (IDirectSound*)&This->IDirectSound8_iface, &desc);
567 if(FAILED(hr))
569 IDirectSoundBuffer8_Release(This->primary->write_emu);
570 This->primary->write_emu = NULL;
575 else if(This->prio_level == DSSCL_WRITEPRIMARY && level != DSSCL_WRITEPRIMARY && This->primary->write_emu)
577 TRACE("Nuking write_emu\n");
578 /* Delete it */
579 IDirectSoundBuffer8_Release(This->primary->write_emu);
580 This->primary->write_emu = NULL;
582 if(SUCCEEDED(hr))
583 This->prio_level = level;
584 out:
585 LeaveCriticalSection(&This->primary->crst);
587 return hr;
590 static HRESULT WINAPI DS8_Compact(IDirectSound8 *iface)
592 DS8Impl *This = impl_from_IDirectSound8(iface);
593 HRESULT hr = S_OK;
595 TRACE("(%p)->()\n", iface);
597 if(!This->primary)
599 WARN("Device not initialized\n");
600 return DSERR_UNINITIALIZED;
603 EnterCriticalSection(&This->primary->crst);
604 if(This->prio_level < DSSCL_PRIORITY)
606 WARN("Coop level not high enough (%u)\n", This->prio_level);
607 hr = DSERR_PRIOLEVELNEEDED;
609 LeaveCriticalSection(&This->primary->crst);
611 return hr;
614 static HRESULT WINAPI DS8_GetSpeakerConfig(IDirectSound8 *iface, DWORD *config)
616 DS8Impl *This = impl_from_IDirectSound8(iface);
617 HRESULT hr = S_OK;
619 TRACE("(%p)->(%p)\n", iface, config);
621 if(!config)
622 return DSERR_INVALIDPARAM;
623 *config = 0;
625 if(!This->primary)
627 WARN("Device not initialized\n");
628 return DSERR_UNINITIALIZED;
631 EnterCriticalSection(&This->primary->crst);
632 *config = This->speaker_config;
633 LeaveCriticalSection(&This->primary->crst);
635 return hr;
638 static HRESULT WINAPI DS8_SetSpeakerConfig(IDirectSound8 *iface, DWORD config)
640 DS8Impl *This = impl_from_IDirectSound8(iface);
641 DWORD geo, speaker;
642 HKEY key;
643 HRESULT hr;
645 TRACE("(%p)->(0x%08x)\n", iface, config);
647 if(!This->primary)
649 WARN("Device not initialized\n");
650 return DSERR_UNINITIALIZED;
653 EnterCriticalSection(&This->primary->crst);
655 geo = DSSPEAKER_GEOMETRY(config);
656 speaker = DSSPEAKER_CONFIG(config);
658 hr = DSERR_INVALIDPARAM;
659 if(geo && (geo < DSSPEAKER_GEOMETRY_MIN || geo > DSSPEAKER_GEOMETRY_MAX))
661 WARN("Invalid speaker angle %u\n", geo);
662 goto out;
664 if(speaker < DSSPEAKER_HEADPHONE || speaker > DSSPEAKER_7POINT1)
666 WARN("Invalid speaker config %u\n", speaker);
667 goto out;
670 hr = DSERR_GENERIC;
671 if(!RegCreateKeyExW(HKEY_LOCAL_MACHINE, speakerconfigkey, 0, NULL, 0, KEY_WRITE, NULL, &key, NULL))
673 RegSetValueExW(key, speakerconfig, 0, REG_DWORD, (const BYTE*)&config, sizeof(DWORD));
674 This->speaker_config = config;
675 RegCloseKey(key);
676 hr = S_OK;
678 out:
679 LeaveCriticalSection(&This->primary->crst);
681 return hr;
684 static HRESULT WINAPI DS8_Initialize(IDirectSound8 *iface, const GUID *devguid)
686 DS8Impl *This = impl_from_IDirectSound8(iface);
687 const ALCchar *drv_name;
688 HRESULT hr;
689 UINT n;
691 TRACE("(%p)->(%s)\n", iface, debugstr_guid(devguid));
693 if(!openal_loaded)
694 return DSERR_NODRIVER;
696 if(This->primary)
698 WARN("Device already initialized\n");
699 return DSERR_ALREADYINITIALIZED;
702 if(!devguid)
703 devguid = &DSDEVID_DefaultPlayback;
704 hr = GetDeviceID(devguid, &This->guid);
705 if(FAILED(hr))
706 return hr;
708 EnterCriticalSection(&openal_crst);
710 for(n = 0;n < devicelistsize;n++)
712 if(devicelist[n]->device && devicelist[n]->is_8 == This->is_8 &&
713 IsEqualGUID(&devicelist[n]->guid, &This->guid))
715 TRACE("Matched already open device %p\n", devicelist[n]);
717 This->device = devicelist[n]->device;
718 This->primary = devicelist[n]->primary;
719 This->deviceref = devicelist[n]->deviceref;
720 InterlockedIncrement(This->deviceref);
722 hr = DS_OK;
723 goto out;
727 if(!This->deviceref)
729 hr = DSERR_OUTOFMEMORY;
730 if(!(This->deviceref=HeapAlloc(GetProcessHeap(), 0, sizeof(LONG))))
731 goto out;
732 This->deviceref[0] = 1;
735 hr = DSERR_NODRIVER;
736 if(!(drv_name=DSOUND_getdevicestrings()) ||
737 memcmp(&This->guid, &DSOUND_renderer_guid, sizeof(GUID)-1) != 0)
739 WARN("No device found\n");
740 goto out;
743 n = This->guid.Data4[7];
744 while(*drv_name && n--)
745 drv_name += strlen(drv_name) + 1;
746 if(!*drv_name)
748 WARN("No device string found\n");
749 goto out;
752 This->device = alcOpenDevice(drv_name);
753 if(!This->device)
755 alcGetError(NULL);
756 WARN("Couldn't open device \"%s\"\n", drv_name);
757 goto out;
759 TRACE("Opened device: %s\n", alcGetString(This->device, ALC_DEVICE_SPECIFIER));
761 hr = DS8Primary_Create(&This->primary, This);
762 if(FAILED(hr))
764 alcCloseDevice(This->device);
765 This->device = NULL;
768 out:
769 LeaveCriticalSection(&openal_crst);
771 return hr;
774 /* I, Maarten Lankhorst, hereby declare this driver certified
775 * What this means.. ? An extra bit set
777 static HRESULT WINAPI DS8_VerifyCertification(IDirectSound8 *iface, DWORD *certified)
779 DS8Impl *This = impl_from_IDirectSound8(iface);
781 TRACE("(%p)->(%p)\n", iface, certified);
783 if(!certified)
784 return DSERR_INVALIDPARAM;
785 *certified = 0;
787 if(!This->primary)
789 WARN("Device not initialized\n");
790 return DSERR_UNINITIALIZED;
793 *certified = DS_CERTIFIED;
795 return DS_OK;
798 static const IDirectSound8Vtbl DS8_Vtbl =
800 DS8_QueryInterface,
801 DS8_AddRef,
802 DS8_Release,
803 DS8_CreateSoundBuffer,
804 DS8_GetCaps,
805 DS8_DuplicateSoundBuffer,
806 DS8_SetCooperativeLevel,
807 DS8_Compact,
808 DS8_GetSpeakerConfig,
809 DS8_SetSpeakerConfig,
810 DS8_Initialize,
811 DS8_VerifyCertification