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
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
38 #include "wine/debug.h"
41 #include "dsound_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
51 #include "dsound_private.h"
53 #ifndef DSSPEAKER_7POINT1
54 #define DSSPEAKER_7POINT1 7
59 static DS8Impl
**devicelist
;
60 static UINT devicelistsize
;
62 static const IDirectSound8Vtbl DS8_Vtbl
;
63 static const IDirectSoundVtbl DS_Vtbl
;
65 static inline DS8Impl
*impl_from_IDirectSound8(IDirectSound8
*iface
)
67 return CONTAINING_RECORD(iface
, DS8Impl
, IDirectSound8_iface
);
70 static inline DS8Impl
*impl_from_IDirectSound(IDirectSound
*iface
)
72 return CONTAINING_RECORD(iface
, DS8Impl
, IDirectSound_iface
);
75 HRESULT
DSOUND_Create(REFIID riid
, void **ds
)
79 if(IsEqualIID(riid
, &IID_IDirectSound8
))
81 hr
= DSOUND_Create8(&IID_IDirectSound8
, ds
);
84 DS8Impl
*impl
= impl_from_IDirectSound8(*ds
);
87 hr
= IDirectSound8_QueryInterface(&impl
->IDirectSound8_iface
, riid
, ds
);
88 IDirectSound8_Release(&impl
->IDirectSound8_iface
);
93 static void DS8Impl_Destroy(DS8Impl
*This
);
95 static const WCHAR speakerconfigkey
[] = {
96 'S','Y','S','T','E','M','\\',
97 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
98 'C','o','n','t','r','o','l','\\',
99 'M','e','d','i','a','R','e','s','o','u','r','c','e','s','\\',
100 'D','i','r','e','c','t','S','o','u','n','d','\\',
101 'S','p','e','a','k','e','r',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',0
104 static const WCHAR speakerconfig
[] = {
105 'S','p','e','a','k','e','r',' ','C','o','n','f','i','g','u','r','a','t','i','o','n',0
108 HRESULT
DSOUND_Create8(REFIID riid
, LPVOID
*ds
)
115 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
117 return E_OUTOFMEMORY
;
118 This
->IDirectSound8_iface
.lpVtbl
= (IDirectSound8Vtbl
*)&DS8_Vtbl
;
119 This
->IDirectSound_iface
.lpVtbl
= (IDirectSoundVtbl
*)&DS_Vtbl
;
122 This
->speaker_config
= DSSPEAKER_COMBINED(DSSPEAKER_5POINT1
, DSSPEAKER_GEOMETRY_WIDE
);
124 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE
, speakerconfigkey
, 0, KEY_READ
, ®key
) == ERROR_SUCCESS
)
126 DWORD type
, conf
, confsize
= sizeof(DWORD
);
128 if(RegQueryValueExW(regkey
, speakerconfig
, NULL
, &type
, (BYTE
*)&conf
, &confsize
) == ERROR_SUCCESS
)
130 if(type
== REG_DWORD
)
131 This
->speaker_config
= conf
;
136 /*RegGetValueW(HKEY_LOCAL_MACHINE, speakerconfigkey, speakerconfig, RRF_RT_REG_DWORD, NULL, &This->speaker_config, NULL);*/
138 hr
= IDirectSound8_QueryInterface(&This
->IDirectSound8_iface
, riid
, ds
);
140 DS8Impl_Destroy(This
);
145 EnterCriticalSection(&openal_crst
);
147 temp
= HeapReAlloc(GetProcessHeap(), 0, devicelist
, sizeof(*devicelist
)*(devicelistsize
+1));
149 temp
= HeapAlloc(GetProcessHeap(), 0, sizeof(*devicelist
)*(devicelistsize
+1));
153 devicelist
[devicelistsize
++] = This
;
155 LeaveCriticalSection(&openal_crst
);
160 static void DS8Impl_Destroy(DS8Impl
*This
)
164 EnterCriticalSection(&openal_crst
);
165 for(i
= 0;i
< devicelistsize
;i
++)
167 if(devicelist
[i
] == This
)
169 devicelist
[i
] = devicelist
[--devicelistsize
];
170 if(devicelistsize
== 0)
172 HeapFree(GetProcessHeap(), 0, devicelist
);
178 LeaveCriticalSection(&openal_crst
);
180 if(This
->deviceref
&& InterlockedDecrement(This
->deviceref
) == 0)
183 DS8Primary_Destroy(This
->primary
);
185 alcCloseDevice(This
->device
);
187 HeapFree(GetProcessHeap(), 0, This
->deviceref
);
191 EnterCriticalSection(&openal_crst
);
192 if(This
->primary
&& This
->primary
->parent
== This
)
194 /* If the primary is referencing this as its parent, update it to
195 * reference another handle for the device */
196 for(i
= 0;i
< devicelistsize
;i
++)
198 if(devicelist
[i
]->primary
== This
->primary
)
200 This
->primary
->parent
= devicelist
[i
];
205 LeaveCriticalSection(&openal_crst
);
208 HeapFree(GetProcessHeap(), 0, This
);
212 static HRESULT WINAPI
DS8_QueryInterface(IDirectSound8
*iface
, REFIID riid
, LPVOID
*ppv
)
214 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
216 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
219 if(IsEqualIID(riid
, &IID_IUnknown
) ||
220 IsEqualIID(riid
, &IID_IDirectSound
))
221 *ppv
= &This
->IDirectSound8_iface
;
222 else if((IsEqualIID(riid
, &IID_IDirectSound8
)))
225 *ppv
= &This
->IDirectSound8_iface
;
228 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
232 IUnknown_AddRef((IUnknown
*)*ppv
);
236 return E_NOINTERFACE
;
239 static ULONG WINAPI
DS8_AddRef(IDirectSound8
*iface
)
241 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
244 ref
= InterlockedIncrement(&This
->ref
);
245 TRACE("Reference count incremented to %"LONGFMT
"d\n", ref
);
250 static ULONG WINAPI
DS8_Release(IDirectSound8
*iface
)
252 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
255 ref
= InterlockedDecrement(&This
->ref
);
256 TRACE("Reference count decremented to %"LONGFMT
"d\n", ref
);
258 DS8Impl_Destroy(This
);
263 static HRESULT WINAPI
DS8_CreateSoundBuffer(IDirectSound8
*iface
, LPCDSBUFFERDESC desc
, LPLPDIRECTSOUNDBUFFER buf
, IUnknown
*pUnkOuter
)
265 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
268 TRACE("(%p)->(%p, %p, %p)\n", iface
, desc
, buf
, pUnkOuter
);
272 WARN("buf is null\n");
273 return DSERR_INVALIDPARAM
;
279 WARN("Aggregation isn't supported\n");
280 return DSERR_NOAGGREGATION
;
282 if(!desc
|| desc
->dwSize
< sizeof(DSBUFFERDESC1
))
284 WARN("Invalid buffer %p/%"LONGFMT
"u\n", desc
, desc
?desc
->dwSize
:0);
285 return DSERR_INVALIDPARAM
;
290 WARN("Device not initialized\n");
291 return DSERR_UNINITIALIZED
;
294 TRACE("Requested buffer:\n"
295 " Size = %"LONGFMT
"u\n"
296 " Flags = 0x%08"LONGFMT
"x\n"
297 " BufferBytes = %"LONGFMT
"u\n",
298 desc
->dwSize
, desc
->dwFlags
, desc
->dwBufferBytes
);
300 if(desc
->dwSize
>= sizeof(DSBUFFERDESC
))
302 if(!(desc
->dwFlags
&DSBCAPS_CTRL3D
))
304 if(!IsEqualGUID(&desc
->guid3DAlgorithm
, &GUID_NULL
))
306 WARN("Invalid 3D algorithm GUID specified for non-3D buffer: %s\n", debugstr_guid(&desc
->guid3DAlgorithm
));
307 return DSERR_INVALIDPARAM
;
311 TRACE("Requested 3D algorithm GUID: %s\n", debugstr_guid(&desc
->guid3DAlgorithm
));
314 /* OpenAL doesn't support playing with 3d and panning at same time.. */
315 if((desc
->dwFlags
&(DSBCAPS_CTRL3D
|DSBCAPS_CTRLPAN
)) == (DSBCAPS_CTRL3D
|DSBCAPS_CTRLPAN
))
318 ERR("Cannot create buffers with 3D and panning control\n");
320 WARN("Cannot create buffers with 3D and panning control\n");
321 return DSERR_INVALIDPARAM
;
324 EnterCriticalSection(&This
->primary
->crst
);
325 if((desc
->dwFlags
&DSBCAPS_PRIMARYBUFFER
))
327 IDirectSoundBuffer
*prim
= &This
->primary
->IDirectSoundBuffer_iface
;
330 if(IDirectSoundBuffer_AddRef(prim
) == 1)
332 hr
= IDirectSoundBuffer_Initialize(prim
, &This
->IDirectSound_iface
, desc
);
335 IDirectSoundBuffer_Release(prim
);
345 hr
= DS8Buffer_Create(&dsb
, This
->primary
, NULL
);
348 hr
= IDirectSoundBuffer8_Initialize(&dsb
->IDirectSoundBuffer8_iface
, &This
->IDirectSound_iface
, desc
);
350 IDirectSoundBuffer8_Release(&dsb
->IDirectSoundBuffer8_iface
);
353 dsb
->bufferlost
= (This
->prio_level
== DSSCL_WRITEPRIMARY
);
354 *buf
= &dsb
->IDirectSoundBuffer_iface
;
358 LeaveCriticalSection(&This
->primary
->crst
);
360 TRACE("%08"LONGFMT
"x\n", hr
);
364 static HRESULT WINAPI
DS8_GetCaps(IDirectSound8
*iface
, LPDSCAPS caps
)
366 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
369 TRACE("(%p)->(%p)\n", iface
, caps
);
373 WARN("Device not initialized\n");
374 return DSERR_UNINITIALIZED
;
377 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
379 WARN("Invalid DSCAPS (%p, %"LONGFMT
"u)\n", caps
, (caps
?caps
->dwSize
:0));
380 return DSERR_INVALIDPARAM
;
383 EnterCriticalSection(&This
->primary
->crst
);
384 count
= This
->primary
->max_sources
;
386 setALContext(This
->primary
->ctx
);
387 caps
->dwFlags
= DSCAPS_CONTINUOUSRATE
|
388 DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYSTEREO
|
389 DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYMONO
|
390 DSCAPS_SECONDARY16BIT
| DSCAPS_SECONDARY8BIT
|
391 DSCAPS_SECONDARYMONO
| DSCAPS_SECONDARYSTEREO
;
392 caps
->dwPrimaryBuffers
= 1;
393 caps
->dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
394 caps
->dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
395 caps
->dwMaxHwMixingAllBuffers
=
396 caps
->dwMaxHwMixingStaticBuffers
=
397 caps
->dwMaxHwMixingStreamingBuffers
=
398 caps
->dwMaxHw3DAllBuffers
=
399 caps
->dwMaxHw3DStaticBuffers
=
400 caps
->dwMaxHw3DStreamingBuffers
= count
;
401 count
-= This
->primary
->nbuffers
;
404 ERR("How did the count drop below 0?\n");
407 caps
->dwFreeHwMixingAllBuffers
=
408 caps
->dwFreeHwMixingStaticBuffers
=
409 caps
->dwFreeHwMixingStreamingBuffers
=
410 caps
->dwFreeHw3DAllBuffers
=
411 caps
->dwFreeHw3DStaticBuffers
=
412 caps
->dwFreeHw3DStreamingBuffers
= count
;
413 caps
->dwTotalHwMemBytes
=
414 caps
->dwFreeHwMemBytes
= 64 * 1024 * 1024;
415 caps
->dwMaxContigFreeHwMemBytes
= caps
->dwFreeHwMemBytes
;
416 caps
->dwUnlockTransferRateHwBuffers
= 4096;
417 caps
->dwPlayCpuOverheadSwBuffers
= 0;
420 LeaveCriticalSection(&This
->primary
->crst
);
424 static HRESULT WINAPI
DS8_DuplicateSoundBuffer(IDirectSound8
*iface
, IDirectSoundBuffer
*in
, IDirectSoundBuffer
**out
)
426 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
431 TRACE("(%p)->(%p, %p)\n", iface
, in
, out
);
435 WARN("Device not initialized\n");
436 return DSERR_UNINITIALIZED
;
441 WARN("Invalid pointer: int = %p, out = %p\n", in
, out
);
442 return DSERR_INVALIDPARAM
;
446 EnterCriticalSection(&This
->primary
->crst
);
448 caps
.dwSize
= sizeof(caps
);
449 hr
= IDirectSoundBuffer_GetCaps(in
, &caps
);
450 if(SUCCEEDED(hr
) && (caps
.dwFlags
&DSBCAPS_PRIMARYBUFFER
))
452 WARN("Cannot duplicate buffer %p, which has DSBCAPS_PRIMARYBUFFER\n", in
);
453 hr
= DSERR_INVALIDPARAM
;
455 if(SUCCEEDED(hr
) && (caps
.dwFlags
&DSBCAPS_CTRLFX
))
457 WARN("Cannot duplicate buffer %p, which has DSBCAPS_CTRLFX\n", in
);
458 hr
= DSERR_INVALIDPARAM
;
461 hr
= DS8Buffer_Create(&buf
, This
->primary
, in
);
464 *out
= &buf
->IDirectSoundBuffer_iface
;
465 hr
= IDirectSoundBuffer_Initialize(*out
, NULL
, NULL
);
469 /* According to MSDN volume isn't copied */
470 if((caps
.dwFlags
&DSBCAPS_CTRLPAN
))
473 if(SUCCEEDED(IDirectSoundBuffer_GetPan(in
, &pan
)))
474 IDirectSoundBuffer_SetPan(*out
, pan
);
476 if((caps
.dwFlags
&DSBCAPS_CTRLFREQUENCY
))
479 if(SUCCEEDED(IDirectSoundBuffer_GetFrequency(in
, &freq
)))
480 IDirectSoundBuffer_SetFrequency(*out
, freq
);
482 if((caps
.dwFlags
&DSBCAPS_CTRL3D
))
484 IDirectSound3DBuffer
*buf3d
;
485 DS3DBUFFER DS3DBuffer
;
488 subhr
= IDirectSound_QueryInterface(in
, &IID_IDirectSound3DBuffer
, (void**)&buf3d
);
491 DS3DBuffer
.dwSize
= sizeof(DS3DBuffer
);
492 subhr
= IDirectSound3DBuffer_GetAllParameters(buf3d
, &DS3DBuffer
);
493 IDirectSound3DBuffer_Release(buf3d
);
496 subhr
= IDirectSoundBuffer_QueryInterface(*out
, &IID_IDirectSound3DBuffer
, (void**)&buf3d
);
499 subhr
= IDirectSound3DBuffer_SetAllParameters(buf3d
, &DS3DBuffer
, DS3D_IMMEDIATE
);
500 IDirectSound3DBuffer_Release(buf3d
);
507 IDirectSoundBuffer_Release(*out
);
511 LeaveCriticalSection(&This
->primary
->crst
);
515 static HRESULT WINAPI
DS8_SetCooperativeLevel(IDirectSound8
*iface
, HWND hwnd
, DWORD level
)
517 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
520 TRACE("(%p)->(%p, %"LONGFMT
"u)\n", iface
, hwnd
, level
);
524 WARN("Device not initialized\n");
525 return DSERR_UNINITIALIZED
;
528 if(level
> DSSCL_WRITEPRIMARY
|| level
< DSSCL_NORMAL
)
530 WARN("Invalid coop level: %"LONGFMT
"u\n", level
);
531 return DSERR_INVALIDPARAM
;
534 EnterCriticalSection(&This
->primary
->crst
);
535 if(level
== DSSCL_WRITEPRIMARY
&& (This
->prio_level
!= DSSCL_WRITEPRIMARY
))
539 for(i
= 0; i
< This
->primary
->nbuffers
; ++i
)
541 DS8Buffer
*buf
= This
->primary
->buffers
[i
];
542 if(FAILED(IDirectSoundBuffer_GetStatus(&buf
->IDirectSoundBuffer8_iface
, &state
)) ||
543 (state
&DSBSTATUS_PLAYING
))
545 WARN("DSSCL_WRITEPRIMARY set with playing buffers!\n");
546 hr
= DSERR_INVALIDCALL
;
549 /* Mark buffer as lost */
552 if(This
->primary
->write_emu
)
554 ERR("Why was there a write_emu?\n");
556 IDirectSoundBuffer8_Release(This
->primary
->write_emu
);
557 This
->primary
->write_emu
= NULL
;
559 if(This
->primary
->flags
)
561 /* Primary has open references.. create write_emu */
565 memset(&desc
, 0, sizeof(desc
));
566 desc
.dwSize
= sizeof(desc
);
567 desc
.dwFlags
= DSBCAPS_LOCHARDWARE
| (This
->primary
->flags
&DSBCAPS_CTRLPAN
);
568 desc
.dwBufferBytes
= This
->primary
->buf_size
;
569 desc
.lpwfxFormat
= &This
->primary
->format
.Format
;
571 hr
= DS8Buffer_Create(&emu
, This
->primary
, NULL
);
574 This
->primary
->write_emu
= &emu
->IDirectSoundBuffer8_iface
;
575 hr
= IDirectSoundBuffer8_Initialize(This
->primary
->write_emu
, &This
->IDirectSound_iface
, &desc
);
578 IDirectSoundBuffer8_Release(This
->primary
->write_emu
);
579 This
->primary
->write_emu
= NULL
;
584 else if(This
->prio_level
== DSSCL_WRITEPRIMARY
&& level
!= DSSCL_WRITEPRIMARY
&& This
->primary
->write_emu
)
586 TRACE("Nuking write_emu\n");
588 IDirectSoundBuffer8_Release(This
->primary
->write_emu
);
589 This
->primary
->write_emu
= NULL
;
592 This
->prio_level
= level
;
594 LeaveCriticalSection(&This
->primary
->crst
);
599 static HRESULT WINAPI
DS8_Compact(IDirectSound8
*iface
)
601 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
604 TRACE("(%p)->()\n", iface
);
608 WARN("Device not initialized\n");
609 return DSERR_UNINITIALIZED
;
612 EnterCriticalSection(&This
->primary
->crst
);
613 if(This
->prio_level
< DSSCL_PRIORITY
)
615 WARN("Coop level not high enough (%"LONGFMT
"u)\n", This
->prio_level
);
616 hr
= DSERR_PRIOLEVELNEEDED
;
618 LeaveCriticalSection(&This
->primary
->crst
);
623 static HRESULT WINAPI
DS8_GetSpeakerConfig(IDirectSound8
*iface
, DWORD
*config
)
625 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
628 TRACE("(%p)->(%p)\n", iface
, config
);
631 return DSERR_INVALIDPARAM
;
636 WARN("Device not initialized\n");
637 return DSERR_UNINITIALIZED
;
640 EnterCriticalSection(&This
->primary
->crst
);
641 *config
= This
->speaker_config
;
642 LeaveCriticalSection(&This
->primary
->crst
);
647 static HRESULT WINAPI
DS8_SetSpeakerConfig(IDirectSound8
*iface
, DWORD config
)
649 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
654 TRACE("(%p)->(0x%08"LONGFMT
"x)\n", iface
, config
);
658 WARN("Device not initialized\n");
659 return DSERR_UNINITIALIZED
;
662 EnterCriticalSection(&This
->primary
->crst
);
664 geo
= DSSPEAKER_GEOMETRY(config
);
665 speaker
= DSSPEAKER_CONFIG(config
);
667 hr
= DSERR_INVALIDPARAM
;
668 if(geo
&& (geo
< DSSPEAKER_GEOMETRY_MIN
|| geo
> DSSPEAKER_GEOMETRY_MAX
))
670 WARN("Invalid speaker angle %"LONGFMT
"u\n", geo
);
673 if(speaker
< DSSPEAKER_HEADPHONE
|| speaker
> DSSPEAKER_7POINT1
)
675 WARN("Invalid speaker config %"LONGFMT
"u\n", speaker
);
680 if(!RegCreateKeyExW(HKEY_LOCAL_MACHINE
, speakerconfigkey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
))
682 RegSetValueExW(key
, speakerconfig
, 0, REG_DWORD
, (const BYTE
*)&config
, sizeof(DWORD
));
683 This
->speaker_config
= config
;
688 LeaveCriticalSection(&This
->primary
->crst
);
693 static HRESULT WINAPI
DS8_Initialize(IDirectSound8
*iface
, const GUID
*devguid
)
695 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
696 const ALCchar
*drv_name
;
700 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(devguid
));
703 return DSERR_NODRIVER
;
707 WARN("Device already initialized\n");
708 return DSERR_ALREADYINITIALIZED
;
712 devguid
= &DSDEVID_DefaultPlayback
;
713 hr
= GetDeviceID(devguid
, &This
->guid
);
717 EnterCriticalSection(&openal_crst
);
719 for(n
= 0;n
< devicelistsize
;n
++)
721 if(devicelist
[n
]->device
&& devicelist
[n
]->is_8
== This
->is_8
&&
722 IsEqualGUID(&devicelist
[n
]->guid
, &This
->guid
))
724 TRACE("Matched already open device %p\n", devicelist
[n
]);
726 This
->device
= devicelist
[n
]->device
;
727 This
->primary
= devicelist
[n
]->primary
;
728 This
->deviceref
= devicelist
[n
]->deviceref
;
729 InterlockedIncrement(This
->deviceref
);
738 hr
= DSERR_OUTOFMEMORY
;
739 if(!(This
->deviceref
=HeapAlloc(GetProcessHeap(), 0, sizeof(LONG
))))
741 This
->deviceref
[0] = 1;
745 if(!(drv_name
=DSOUND_getdevicestrings()) ||
746 memcmp(&This
->guid
, &DSOUND_renderer_guid
, sizeof(GUID
)-1) != 0)
748 WARN("No device found\n");
752 n
= This
->guid
.Data4
[7];
753 while(*drv_name
&& n
--)
754 drv_name
+= strlen(drv_name
) + 1;
757 WARN("No device string found\n");
761 This
->device
= alcOpenDevice(drv_name
);
765 WARN("Couldn't open device \"%s\"\n", drv_name
);
768 TRACE("Opened device: %s\n", alcGetString(This
->device
, ALC_DEVICE_SPECIFIER
));
770 hr
= DS8Primary_Create(&This
->primary
, This
);
773 alcCloseDevice(This
->device
);
778 LeaveCriticalSection(&openal_crst
);
783 /* I, Maarten Lankhorst, hereby declare this driver certified
784 * What this means.. ? An extra bit set
786 static HRESULT WINAPI
DS8_VerifyCertification(IDirectSound8
*iface
, DWORD
*certified
)
788 DS8Impl
*This
= impl_from_IDirectSound8(iface
);
790 TRACE("(%p)->(%p)\n", iface
, certified
);
793 return DSERR_INVALIDPARAM
;
798 WARN("Device not initialized\n");
799 return DSERR_UNINITIALIZED
;
802 *certified
= DS_CERTIFIED
;
807 static const IDirectSound8Vtbl DS8_Vtbl
= {
811 DS8_CreateSoundBuffer
,
813 DS8_DuplicateSoundBuffer
,
814 DS8_SetCooperativeLevel
,
816 DS8_GetSpeakerConfig
,
817 DS8_SetSpeakerConfig
,
819 DS8_VerifyCertification
823 static HRESULT WINAPI
DS_QueryInterface(IDirectSound
*iface
, REFIID riid
, LPVOID
*ppv
)
825 DS8Impl
*This
= impl_from_IDirectSound(iface
);
826 return DS8_QueryInterface(&This
->IDirectSound8_iface
, riid
, ppv
);
829 static ULONG WINAPI
DS_AddRef(IDirectSound
*iface
)
831 DS8Impl
*This
= impl_from_IDirectSound(iface
);
832 return DS8_AddRef(&This
->IDirectSound8_iface
);
835 static ULONG WINAPI
DS_Release(IDirectSound
*iface
)
837 DS8Impl
*This
= impl_from_IDirectSound(iface
);
838 return DS8_Release(&This
->IDirectSound8_iface
);
841 static HRESULT WINAPI
DS_CreateSoundBuffer(IDirectSound
*iface
, LPCDSBUFFERDESC desc
, LPLPDIRECTSOUNDBUFFER buf
, IUnknown
*pUnkOuter
)
843 DS8Impl
*This
= impl_from_IDirectSound(iface
);
844 return DS8_CreateSoundBuffer(&This
->IDirectSound8_iface
, desc
, buf
, pUnkOuter
);
847 static HRESULT WINAPI
DS_GetCaps(IDirectSound
*iface
, LPDSCAPS caps
)
849 DS8Impl
*This
= impl_from_IDirectSound(iface
);
850 return DS8_GetCaps(&This
->IDirectSound8_iface
, caps
);
852 static HRESULT WINAPI
DS_DuplicateSoundBuffer(IDirectSound
*iface
, IDirectSoundBuffer
*in
, IDirectSoundBuffer
**out
)
854 DS8Impl
*This
= impl_from_IDirectSound(iface
);
855 return DS8_DuplicateSoundBuffer(&This
->IDirectSound8_iface
, in
, out
);
858 static HRESULT WINAPI
DS_SetCooperativeLevel(IDirectSound
*iface
, HWND hwnd
, DWORD level
)
860 DS8Impl
*This
= impl_from_IDirectSound(iface
);
861 return DS8_SetCooperativeLevel(&This
->IDirectSound8_iface
, hwnd
, level
);
864 static HRESULT WINAPI
DS_Compact(IDirectSound
*iface
)
866 DS8Impl
*This
= impl_from_IDirectSound(iface
);
867 return DS8_Compact(&This
->IDirectSound8_iface
);
870 static HRESULT WINAPI
DS_GetSpeakerConfig(IDirectSound
*iface
, DWORD
*config
)
872 DS8Impl
*This
= impl_from_IDirectSound(iface
);
873 return DS8_GetSpeakerConfig(&This
->IDirectSound8_iface
, config
);
876 static HRESULT WINAPI
DS_SetSpeakerConfig(IDirectSound
*iface
, DWORD config
)
878 DS8Impl
*This
= impl_from_IDirectSound(iface
);
879 return DS8_SetSpeakerConfig(&This
->IDirectSound8_iface
, config
);
882 static HRESULT WINAPI
DS_Initialize(IDirectSound
*iface
, const GUID
*devguid
)
884 DS8Impl
*This
= impl_from_IDirectSound(iface
);
885 return DS8_Initialize(&This
->IDirectSound8_iface
, devguid
);
888 static const IDirectSoundVtbl DS_Vtbl
= {
892 DS_CreateSoundBuffer
,
894 DS_DuplicateSoundBuffer
,
895 DS_SetCooperativeLevel
,