Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
dfaef530
Commit
dfaef530
authored
Jan 20, 2015
by
Francois Gouget
Committed by
Alexandre Julliard
Jan 20, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dsound: Reorder the interfaces to remove the need for forward declarations.
parent
82c298ee
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
838 additions
and
851 deletions
+838
-851
dsound.c
dlls/dsound/dsound.c
+838
-837
dsound_private.h
dlls/dsound/dsound_private.h
+0
-14
No files found.
dlls/dsound/dsound.c
View file @
dfaef530
...
...
@@ -119,1075 +119,1076 @@ static void _dump_DSBCAPS(DWORD xmask) {
TRACE
(
"%s "
,
flags
[
i
].
name
);
}
static
void
directsound_destroy
(
IDirectSoundImpl
*
This
)
{
if
(
This
->
device
)
DirectSoundDevice_Release
(
This
->
device
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
TRACE
(
"(%p) released
\n
"
,
This
);
}
/*******************************************************************************
*
IUnknown Implementation for DirectSound
*
DirectSoundDevice
*/
static
inline
IDirectSoundImpl
*
impl_from_IUnknown
(
IUnknown
*
ifa
ce
)
static
HRESULT
DirectSoundDevice_Create
(
DirectSoundDevice
**
ppDevi
ce
)
{
return
CONTAINING_RECORD
(
iface
,
IDirectSoundImpl
,
IUnknown_inner
)
;
}
DirectSoundDevice
*
device
;
TRACE
(
"(%p)
\n
"
,
ppDevice
);
static
HRESULT
WINAPI
IUnknownImpl_QueryInterface
(
IUnknown
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
IDirectSoundImpl
*
This
=
impl_from_IUnknown
(
iface
);
/* Allocate memory */
device
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
DirectSoundDevice
));
if
(
device
==
NULL
)
{
WARN
(
"out of memory
\n
"
);
return
DSERR_OUTOFMEMORY
;
}
TRACE
(
"(%p,%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppv
);
device
->
ref
=
1
;
device
->
priolevel
=
DSSCL_NORMAL
;
device
->
state
=
STATE_STOPPED
;
device
->
speaker_config
=
DSSPEAKER_COMBINED
(
DSSPEAKER_STEREO
,
DSSPEAKER_GEOMETRY_WIDE
);
if
(
!
ppv
)
{
WARN
(
"invalid parameter
\n
"
);
return
E_INVALIDARG
;
}
*
ppv
=
NULL
;
DSOUND_ParseSpeakerConfig
(
device
);
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
*
ppv
=
&
This
->
IUnknown_inner
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IDirectSound
)
||
(
IsEqualIID
(
riid
,
&
IID_IDirectSound8
)
&&
This
->
has_ds8
))
*
ppv
=
&
This
->
IDirectSound8_iface
;
else
{
WARN
(
"unknown IID %s
\n
"
,
debugstr_guid
(
riid
));
return
E_NOINTERFACE
;
/* 3D listener initial parameters */
device
->
ds3dl
.
dwSize
=
sizeof
(
DS3DLISTENER
);
device
->
ds3dl
.
vPosition
.
x
=
0
.
0
;
device
->
ds3dl
.
vPosition
.
y
=
0
.
0
;
device
->
ds3dl
.
vPosition
.
z
=
0
.
0
;
device
->
ds3dl
.
vVelocity
.
x
=
0
.
0
;
device
->
ds3dl
.
vVelocity
.
y
=
0
.
0
;
device
->
ds3dl
.
vVelocity
.
z
=
0
.
0
;
device
->
ds3dl
.
vOrientFront
.
x
=
0
.
0
;
device
->
ds3dl
.
vOrientFront
.
y
=
0
.
0
;
device
->
ds3dl
.
vOrientFront
.
z
=
1
.
0
;
device
->
ds3dl
.
vOrientTop
.
x
=
0
.
0
;
device
->
ds3dl
.
vOrientTop
.
y
=
1
.
0
;
device
->
ds3dl
.
vOrientTop
.
z
=
0
.
0
;
device
->
ds3dl
.
flDistanceFactor
=
DS3D_DEFAULTDISTANCEFACTOR
;
device
->
ds3dl
.
flRolloffFactor
=
DS3D_DEFAULTROLLOFFFACTOR
;
device
->
ds3dl
.
flDopplerFactor
=
DS3D_DEFAULTDOPPLERFACTOR
;
device
->
prebuf
=
ds_snd_queue_max
;
device
->
guid
=
GUID_NULL
;
/* Set default wave format (may need it for waveOutOpen) */
device
->
pwfx
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
WAVEFORMATEXTENSIBLE
));
device
->
primary_pwfx
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
WAVEFORMATEXTENSIBLE
));
if
(
!
device
->
pwfx
||
!
device
->
primary_pwfx
)
{
WARN
(
"out of memory
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
primary_pwfx
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
pwfx
);
HeapFree
(
GetProcessHeap
(),
0
,
device
);
return
DSERR_OUTOFMEMORY
;
}
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
return
S_OK
;
}
device
->
pwfx
->
wFormatTag
=
WAVE_FORMAT_PCM
;
device
->
pwfx
->
nSamplesPerSec
=
22050
;
device
->
pwfx
->
wBitsPerSample
=
8
;
device
->
pwfx
->
nChannels
=
2
;
device
->
pwfx
->
nBlockAlign
=
device
->
pwfx
->
wBitsPerSample
*
device
->
pwfx
->
nChannels
/
8
;
device
->
pwfx
->
nAvgBytesPerSec
=
device
->
pwfx
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
cbSize
=
0
;
memcpy
(
device
->
primary_pwfx
,
device
->
pwfx
,
sizeof
(
*
device
->
pwfx
));
static
ULONG
WINAPI
IUnknownImpl_AddRef
(
IUnknown
*
iface
)
{
IDirectSoundImpl
*
This
=
impl_from_IUnknown
(
iface
);
ULONG
ref
=
InterlockedIncrement
(
&
This
->
ref
);
InitializeCriticalSection
(
&
(
device
->
mixlock
));
device
->
mixlock
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": DirectSoundDevice.mixlock"
);
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
RtlInitializeResource
(
&
(
device
->
buffer_list_lock
)
);
if
(
ref
==
1
)
InterlockedIncrement
(
&
This
->
numIfaces
);
*
ppDevice
=
device
;
return
ref
;
return
DS_OK
;
}
static
ULONG
WINAPI
IUnknownImpl_Release
(
IUnknown
*
ifa
ce
)
static
ULONG
DirectSoundDevice_AddRef
(
DirectSoundDevice
*
devi
ce
)
{
IDirectSoundImpl
*
This
=
impl_from_IUnknown
(
iface
);
ULONG
ref
=
InterlockedDecrement
(
&
This
->
ref
);
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
if
(
!
ref
&&
!
InterlockedDecrement
(
&
This
->
numIfaces
))
directsound_destroy
(
This
);
ULONG
ref
=
InterlockedIncrement
(
&
(
device
->
ref
));
TRACE
(
"(%p) ref was %d
\n
"
,
device
,
ref
-
1
);
return
ref
;
}
static
const
IUnknownVtbl
unk_vtbl
=
ULONG
DirectSoundDevice_Release
(
DirectSoundDevice
*
device
)
{
IUnknownImpl_QueryInterface
,
IUnknownImpl_AddRef
,
IUnknownImpl_Release
};
HRESULT
hr
;
ULONG
ref
=
InterlockedDecrement
(
&
(
device
->
ref
));
TRACE
(
"(%p) ref was %u
\n
"
,
device
,
ref
+
1
);
if
(
!
ref
)
{
int
i
;
/*******************************************************************************
* IDirectSound and IDirectSound8 Implementation
*/
static
inline
IDirectSoundImpl
*
impl_from_IDirectSound8
(
IDirectSound8
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
IDirectSoundImpl
,
IDirectSound8_iface
);
}
SetEvent
(
device
->
sleepev
);
if
(
device
->
thread
)
{
WaitForSingleObject
(
device
->
thread
,
INFINITE
);
CloseHandle
(
device
->
thread
);
}
CloseHandle
(
device
->
sleepev
);
static
HRESULT
WINAPI
IDirectSound8Impl_QueryInterface
(
IDirectSound8
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p,%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppv
);
return
IUnknown_QueryInterface
(
This
->
outer_unk
,
riid
,
ppv
);
}
EnterCriticalSection
(
&
DSOUND_renderers_lock
);
list_remove
(
&
device
->
entry
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
static
ULONG
WINAPI
IDirectSound8Impl_AddRef
(
IDirectSound8
*
iface
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
ULONG
ref
=
InterlockedIncrement
(
&
This
->
refds
);
/* It is allowed to release this object even when buffers are playing */
if
(
device
->
buffers
)
{
WARN
(
"%d secondary buffers not released
\n
"
,
device
->
nrofbuffers
);
for
(
i
=
0
;
i
<
device
->
nrofbuffers
;
i
++
)
secondarybuffer_destroy
(
device
->
buffers
[
i
]);
}
TRACE
(
"(%p) refds=%d
\n
"
,
This
,
ref
);
hr
=
DSOUND_PrimaryDestroy
(
device
);
if
(
hr
!=
DS_OK
)
WARN
(
"DSOUND_PrimaryDestroy failed
\n
"
);
if
(
ref
==
1
)
InterlockedIncrement
(
&
This
->
numIfaces
);
if
(
device
->
client
)
IAudioClient_Release
(
device
->
client
);
if
(
device
->
render
)
IAudioRenderClient_Release
(
device
->
render
);
if
(
device
->
clock
)
IAudioClock_Release
(
device
->
clock
);
if
(
device
->
volume
)
IAudioStreamVolume_Release
(
device
->
volume
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
tmp_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
mix_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
buffer
);
RtlDeleteResource
(
&
device
->
buffer_list_lock
);
device
->
mixlock
.
DebugInfo
->
Spare
[
0
]
=
0
;
DeleteCriticalSection
(
&
device
->
mixlock
);
HeapFree
(
GetProcessHeap
(),
0
,
device
);
TRACE
(
"(%p) released
\n
"
,
device
);
}
return
ref
;
}
static
ULONG
WINAPI
IDirectSound8Impl_Release
(
IDirectSound8
*
iface
)
BOOL
DSOUND_check_supported
(
IAudioClient
*
client
,
DWORD
rate
,
DWORD
depth
,
WORD
channels
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
ULONG
ref
=
InterlockedDecrement
(
&
(
This
->
refds
));
TRACE
(
"(%p) refds=%d
\n
"
,
This
,
ref
);
WAVEFORMATEX
fmt
,
*
junk
;
HRESULT
hr
;
if
(
!
ref
&&
!
InterlockedDecrement
(
&
This
->
numIfaces
))
directsound_destroy
(
This
);
fmt
.
wFormatTag
=
WAVE_FORMAT_PCM
;
fmt
.
nChannels
=
channels
;
fmt
.
nSamplesPerSec
=
rate
;
fmt
.
wBitsPerSample
=
depth
;
fmt
.
nBlockAlign
=
(
channels
*
depth
)
/
8
;
fmt
.
nAvgBytesPerSec
=
rate
*
fmt
.
nBlockAlign
;
fmt
.
cbSize
=
0
;
return
ref
;
}
hr
=
IAudioClient_IsFormatSupported
(
client
,
AUDCLNT_SHAREMODE_SHARED
,
&
fmt
,
&
junk
);
if
(
SUCCEEDED
(
hr
))
CoTaskMemFree
(
junk
);
static
HRESULT
WINAPI
IDirectSound8Impl_CreateSoundBuffer
(
IDirectSound8
*
iface
,
const
DSBUFFERDESC
*
dsbd
,
IDirectSoundBuffer
**
ppdsb
,
IUnknown
*
lpunk
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p,%p,%p,%p)
\n
"
,
This
,
dsbd
,
ppdsb
,
lpunk
);
return
DirectSoundDevice_CreateSoundBuffer
(
This
->
device
,
dsbd
,
ppdsb
,
lpunk
,
This
->
has_ds8
);
return
hr
==
S_OK
;
}
static
HRESULT
WINAPI
IDirectSound8Impl_GetCaps
(
IDirectSound8
*
iface
,
DSCAPS
*
dscaps
)
HRESULT
DirectSoundDevice_Initialize
(
DirectSoundDevice
**
ppDevice
,
LPCGUID
lpcGUID
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
HRESULT
hr
=
DS_OK
;
GUID
devGUID
;
DirectSoundDevice
*
device
;
IMMDevice
*
mmdevice
;
TRACE
(
"(%p,
%p)
\n
"
,
This
,
dscaps
);
TRACE
(
"(%p,
%s)
\n
"
,
ppDevice
,
debugstr_guid
(
lpcGUID
)
);
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
if
(
!
dscaps
)
{
WARN
(
"invalid parameter: dscaps = NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
if
(
dscaps
->
dwSize
<
sizeof
(
*
dscaps
))
{
WARN
(
"invalid parameter: dscaps->dwSize = %d
\n
"
,
dscaps
->
dwSize
);
return
DSERR_INVALIDPARAM
;
if
(
*
ppDevice
!=
NULL
)
{
WARN
(
"already initialized
\n
"
);
return
DSERR_ALREADYINITIALIZED
;
}
dscaps
->
dwFlags
=
This
->
device
->
drvcaps
.
dwFlags
;
dscaps
->
dwMinSecondarySampleRate
=
This
->
device
->
drvcaps
.
dwMinSecondarySampleRate
;
dscaps
->
dwMaxSecondarySampleRate
=
This
->
device
->
drvcaps
.
dwMaxSecondarySampleRate
;
dscaps
->
dwPrimaryBuffers
=
This
->
device
->
drvcaps
.
dwPrimaryBuffers
;
dscaps
->
dwMaxHwMixingAllBuffers
=
This
->
device
->
drvcaps
.
dwMaxHwMixingAllBuffers
;
dscaps
->
dwMaxHwMixingStaticBuffers
=
This
->
device
->
drvcaps
.
dwMaxHwMixingStaticBuffers
;
dscaps
->
dwMaxHwMixingStreamingBuffers
=
This
->
device
->
drvcaps
.
dwMaxHwMixingStreamingBuffers
;
dscaps
->
dwFreeHwMixingAllBuffers
=
This
->
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
;
/* Default device? */
if
(
!
lpcGUID
||
IsEqualGUID
(
lpcGUID
,
&
GUID_NULL
))
lpcGUID
=
&
DSDEVID_DefaultPlayback
;
if
(
This
->
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
>
0
)
{
dscaps
->
dwFreeHwMixingStaticBuffers
=
This
->
device
->
drvcaps
.
dwFreeHwMixingStaticBuffers
;
dscaps
->
dwFreeHwMixingStreamingBuffers
=
This
->
device
->
drvcaps
.
dwFreeHwMixingStreamingBuffers
;
}
else
{
dscaps
->
dwFreeHwMixingStaticBuffers
=
0
;
dscaps
->
dwFreeHwMixingStreamingBuffers
=
0
;
if
(
IsEqualGUID
(
lpcGUID
,
&
DSDEVID_DefaultCapture
)
||
IsEqualGUID
(
lpcGUID
,
&
DSDEVID_DefaultVoiceCapture
))
return
DSERR_NODRIVER
;
if
(
GetDeviceID
(
lpcGUID
,
&
devGUID
)
!=
DS_OK
)
{
WARN
(
"invalid parameter: lpcGUID
\n
"
);
return
DSERR_INVALIDPARAM
;
}
dscaps
->
dwMaxHw3DAllBuffers
=
This
->
device
->
drvcaps
.
dwMaxHw3DAllBuffers
;
dscaps
->
dwMaxHw3DStaticBuffers
=
This
->
device
->
drvcaps
.
dwMaxHw3DStaticBuffers
;
dscaps
->
dwMaxHw3DStreamingBuffers
=
This
->
device
->
drvcaps
.
dwMaxHw3DStreamingBuffers
;
dscaps
->
dwFreeHw3DAllBuffers
=
This
->
device
->
drvcaps
.
dwFreeHw3DAllBuffers
;
dscaps
->
dwFreeHw3DStaticBuffers
=
This
->
device
->
drvcaps
.
dwFreeHw3DStaticBuffers
;
dscaps
->
dwFreeHw3DStreamingBuffers
=
This
->
device
->
drvcaps
.
dwFreeHw3DStreamingBuffers
;
dscaps
->
dwTotalHwMemBytes
=
This
->
device
->
drvcaps
.
dwTotalHwMemBytes
;
dscaps
->
dwFreeHwMemBytes
=
This
->
device
->
drvcaps
.
dwFreeHwMemBytes
;
dscaps
->
dwMaxContigFreeHwMemBytes
=
This
->
device
->
drvcaps
.
dwMaxContigFreeHwMemBytes
;
dscaps
->
dwUnlockTransferRateHwBuffers
=
This
->
device
->
drvcaps
.
dwUnlockTransferRateHwBuffers
;
dscaps
->
dwPlayCpuOverheadSwBuffers
=
This
->
device
->
drvcaps
.
dwPlayCpuOverheadSwBuffers
;
if
(
TRACE_ON
(
dsound
))
{
TRACE
(
"(flags=0x%08x:
\n
"
,
dscaps
->
dwFlags
);
_dump_DSCAPS
(
dscaps
->
dwFlags
);
TRACE
(
")
\n
"
);
}
return
DS_OK
;
}
static
HRESULT
WINAPI
IDirectSound8Impl_DuplicateSoundBuffer
(
IDirectSound8
*
iface
,
IDirectSoundBuffer
*
psb
,
IDirectSoundBuffer
**
ppdsb
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p,%p,%p)
\n
"
,
This
,
psb
,
ppdsb
);
return
DirectSoundDevice_DuplicateSoundBuffer
(
This
->
device
,
psb
,
ppdsb
);
}
static
HRESULT
WINAPI
IDirectSound8Impl_SetCooperativeLevel
(
IDirectSound8
*
iface
,
HWND
hwnd
,
DWORD
level
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
DirectSoundDevice
*
device
=
This
->
device
;
DWORD
oldlevel
;
HRESULT
hr
=
S_OK
;
TRACE
(
"(%p,%p,%s)
\n
"
,
This
,
hwnd
,
dumpCooperativeLevel
(
level
));
hr
=
get_mmdevice
(
eRender
,
&
devGUID
,
&
mmdevice
);
if
(
FAILED
(
hr
))
return
hr
;
if
(
!
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
EnterCriticalSection
(
&
DSOUND_renderers_lock
);
if
(
level
==
DSSCL_PRIORITY
||
level
==
DSSCL_EXCLUSIVE
)
{
WARN
(
"level=%s not fully supported
\n
"
,
level
==
DSSCL_PRIORITY
?
"DSSCL_PRIORITY"
:
"DSSCL_EXCLUSIVE"
);
LIST_FOR_EACH_ENTRY
(
device
,
&
DSOUND_renderers
,
DirectSoundDevice
,
entry
){
if
(
IsEqualGUID
(
&
device
->
guid
,
&
devGUID
)){
IMMDevice_Release
(
mmdevice
);
DirectSoundDevice_AddRef
(
device
);
*
ppDevice
=
device
;
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
return
DS_OK
;
}
}
RtlAcquireResourceExclusive
(
&
device
->
buffer_list_lock
,
TRUE
);
EnterCriticalSection
(
&
device
->
mixlock
);
oldlevel
=
device
->
priolevel
;
device
->
priolevel
=
level
;
if
((
level
==
DSSCL_WRITEPRIMARY
)
!=
(
oldlevel
==
DSSCL_WRITEPRIMARY
))
{
hr
=
DSOUND_ReopenDevice
(
device
,
level
==
DSSCL_WRITEPRIMARY
);
if
(
FAILED
(
hr
))
device
->
priolevel
=
oldlevel
;
else
DSOUND_PrimaryOpen
(
device
);
hr
=
DirectSoundDevice_Create
(
&
device
);
if
(
FAILED
(
hr
)){
WARN
(
"DirectSoundDevice_Create failed
\n
"
);
IMMDevice_Release
(
mmdevice
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
return
hr
;
}
LeaveCriticalSection
(
&
device
->
mixlock
);
RtlReleaseResource
(
&
device
->
buffer_list_lock
);
return
hr
;
}
static
HRESULT
WINAPI
IDirectSound8Impl_Compact
(
IDirectSound8
*
iface
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p)
\n
"
,
This
);
device
->
mmdevice
=
mmdevice
;
device
->
guid
=
devGUID
;
device
->
sleepev
=
CreateEventW
(
0
,
0
,
0
,
0
);
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
hr
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
FAILED
(
hr
))
{
HeapFree
(
GetProcessHeap
(),
0
,
device
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
IMMDevice_Release
(
mmdevice
);
WARN
(
"DSOUND_ReopenDevice failed: %08x
\n
"
,
hr
);
return
hr
;
}
if
(
This
->
device
->
priolevel
<
DSSCL_PRIORITY
)
{
WARN
(
"incorrect priority level
\n
"
);
return
DSERR_PRIOLEVELNEEDED
;
}
return
DS_OK
;
}
ZeroMemory
(
&
device
->
drvcaps
,
sizeof
(
device
->
drvcaps
));
static
HRESULT
WINAPI
IDirectSound8Impl_GetSpeakerConfig
(
IDirectSound8
*
iface
,
DWORD
*
config
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
8
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
8
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
8
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
8
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
8
,
1
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY8BIT
|
DSCAPS_PRIMARYMONO
;
TRACE
(
"(%p, %p)
\n
"
,
This
,
config
);
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
16
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
16
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
16
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
16
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
16
,
1
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY16BIT
|
DSCAPS_PRIMARYMONO
;
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
if
(
!
config
)
{
WARN
(
"invalid parameter: config == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
8
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
8
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
8
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
8
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
8
,
2
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY8BIT
|
DSCAPS_PRIMARYSTEREO
;
WARN
(
"not fully functional
\n
"
);
*
config
=
This
->
device
->
speaker_config
;
return
DS_OK
;
}
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
16
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
16
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
16
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
16
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
16
,
2
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY16BIT
|
DSCAPS_PRIMARYSTEREO
;
static
HRESULT
WINAPI
IDirectSound8Impl_SetSpeakerConfig
(
IDirectSound8
*
iface
,
DWORD
config
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
/* the dsound mixer supports all of the following */
device
->
drvcaps
.
dwFlags
|=
DSCAPS_SECONDARY8BIT
|
DSCAPS_SECONDARY16BIT
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_SECONDARYMONO
|
DSCAPS_SECONDARYSTEREO
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_CONTINUOUSRATE
;
TRACE
(
"(%p,0x%08x)
\n
"
,
This
,
config
);
device
->
drvcaps
.
dwPrimaryBuffers
=
1
;
device
->
drvcaps
.
dwMinSecondarySampleRate
=
DSBFREQUENCY_MIN
;
device
->
drvcaps
.
dwMaxSecondarySampleRate
=
DSBFREQUENCY_MAX
;
device
->
drvcaps
.
dwMaxHwMixingAllBuffers
=
16
;
device
->
drvcaps
.
dwMaxHwMixingStaticBuffers
=
1
;
device
->
drvcaps
.
dwMaxHwMixingStreamingBuffers
=
1
;
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
=
device
->
drvcaps
.
dwMaxHwMixingAllBuffers
;
device
->
drvcaps
.
dwFreeHwMixingStaticBuffers
=
device
->
drvcaps
.
dwMaxHwMixingStaticBuffers
;
device
->
drvcaps
.
dwFreeHwMixingStreamingBuffers
=
device
->
drvcaps
.
dwMaxHwMixingStreamingBuffers
;
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
ZeroMemory
(
&
device
->
volpan
,
sizeof
(
device
->
volpan
));
/* NOP on Vista and above */
hr
=
DSOUND_PrimaryCreate
(
device
);
if
(
hr
==
DS_OK
)
{
device
->
thread
=
CreateThread
(
0
,
0
,
DSOUND_mixthread
,
device
,
0
,
0
);
SetThreadPriority
(
device
->
thread
,
THREAD_PRIORITY_TIME_CRITICAL
);
}
else
WARN
(
"DSOUND_PrimaryCreate failed: %08x
\n
"
,
hr
);
return
DS_OK
;
}
*
ppDevice
=
device
;
list_add_tail
(
&
DSOUND_renderers
,
&
device
->
entry
);
static
HRESULT
WINAPI
IDirectSound8Impl_Initialize
(
IDirectSound8
*
iface
,
const
GUID
*
lpcGuid
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p, %s)
\n
"
,
This
,
debugstr_guid
(
lpcGuid
));
return
DirectSoundDevice_Initialize
(
&
This
->
device
,
lpcGuid
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
return
hr
;
}
static
HRESULT
WINAPI
IDirectSound8Impl_VerifyCertification
(
IDirectSound8
*
iface
,
DWORD
*
certified
)
HRESULT
DirectSoundDevice_CreateSoundBuffer
(
DirectSoundDevice
*
device
,
LPCDSBUFFERDESC
dsbd
,
LPLPDIRECTSOUNDBUFFER
ppdsb
,
LPUNKNOWN
lpunk
,
BOOL
from8
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p, %p)
\n
"
,
This
,
certified
);
HRESULT
hres
=
DS_OK
;
TRACE
(
"(%p,%p,%p,%p)
\n
"
,
device
,
dsbd
,
ppdsb
,
lpunk
);
if
(
!
This
->
device
)
{
if
(
device
==
NULL
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
if
(
This
->
device
->
drvcaps
.
dwFlags
&
DSCAPS_CERTIFIED
)
*
certified
=
DS_CERTIFIED
;
else
*
certified
=
DS_UNCERTIFIED
;
return
DS_OK
;
}
if
(
dsbd
==
NULL
)
{
WARN
(
"invalid parameter: dsbd == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
static
const
IDirectSound8Vtbl
ds8_vtbl
=
{
IDirectSound8Impl_QueryInterface
,
IDirectSound8Impl_AddRef
,
IDirectSound8Impl_Release
,
IDirectSound8Impl_CreateSoundBuffer
,
IDirectSound8Impl_GetCaps
,
IDirectSound8Impl_DuplicateSoundBuffer
,
IDirectSound8Impl_SetCooperativeLevel
,
IDirectSound8Impl_Compact
,
IDirectSound8Impl_GetSpeakerConfig
,
IDirectSound8Impl_SetSpeakerConfig
,
IDirectSound8Impl_Initialize
,
IDirectSound8Impl_VerifyCertification
};
if
(
dsbd
->
dwSize
!=
sizeof
(
DSBUFFERDESC
)
&&
dsbd
->
dwSize
!=
sizeof
(
DSBUFFERDESC1
))
{
WARN
(
"invalid parameter: dsbd
\n
"
);
return
DSERR_INVALIDPARAM
;
}
HRESULT
IDirectSoundImpl_Create
(
IUnknown
*
outer_unk
,
REFIID
riid
,
void
**
ppv
,
BOOL
has_ds8
)
{
IDirectSoundImpl
*
obj
;
HRESULT
hr
;
if
(
ppdsb
==
NULL
)
{
WARN
(
"invalid parameter: ppdsb == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
*
ppdsb
=
NULL
;
TRACE
(
"(%s, %p)
\n
"
,
debugstr_guid
(
riid
),
ppv
);
if
(
TRACE_ON
(
dsound
))
{
TRACE
(
"(structsize=%d)
\n
"
,
dsbd
->
dwSize
);
TRACE
(
"(flags=0x%08x:
\n
"
,
dsbd
->
dwFlags
);
_dump_DSBCAPS
(
dsbd
->
dwFlags
);
TRACE
(
")
\n
"
);
TRACE
(
"(bufferbytes=%d)
\n
"
,
dsbd
->
dwBufferBytes
);
TRACE
(
"(lpwfxFormat=%p)
\n
"
,
dsbd
->
lpwfxFormat
);
}
*
ppv
=
NULL
;
obj
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
*
obj
));
if
(
!
obj
)
{
WARN
(
"out of memory
\n
"
);
return
DSERR_OUTOFMEMORY
;
if
(
!
(
dsbd
->
dwFlags
&
DSBCAPS_PRIMARYBUFFER
)
&&
dsbd
->
dwFlags
&
DSBCAPS_LOCHARDWARE
&&
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
==
0
)
{
WARN
(
"ran out of emulated hardware buffers
\n
"
);
return
DSERR_ALLOCATED
;
}
setup_dsound_options
();
if
(
dsbd
->
dwFlags
&
DSBCAPS_PRIMARYBUFFER
)
{
if
(
dsbd
->
lpwfxFormat
!=
NULL
)
{
WARN
(
"invalid parameter: dsbd->lpwfxFormat must be NULL for "
"primary buffer
\n
"
);
return
DSERR_INVALIDPARAM
;
}
obj
->
IUnknown_inner
.
lpVtbl
=
&
unk_vtbl
;
obj
->
IDirectSound8_iface
.
lpVtbl
=
&
ds8_vtbl
;
obj
->
ref
=
1
;
obj
->
refds
=
0
;
obj
->
numIfaces
=
1
;
obj
->
device
=
NULL
;
obj
->
has_ds8
=
has_ds8
;
if
(
device
->
primary
)
{
WARN
(
"Primary Buffer already created
\n
"
);
IDirectSoundBuffer_AddRef
((
LPDIRECTSOUNDBUFFER8
)(
device
->
primary
));
*
ppdsb
=
(
LPDIRECTSOUNDBUFFER
)(
device
->
primary
);
}
else
{
hres
=
primarybuffer_create
(
device
,
&
device
->
primary
,
dsbd
);
if
(
device
->
primary
)
{
*
ppdsb
=
(
IDirectSoundBuffer
*
)
&
device
->
primary
->
IDirectSoundBuffer8_iface
;
device
->
primary
->
dsbd
.
dwFlags
&=
~
(
DSBCAPS_LOCHARDWARE
|
DSBCAPS_LOCSOFTWARE
);
device
->
primary
->
dsbd
.
dwFlags
|=
DSBCAPS_LOCSOFTWARE
;
}
else
WARN
(
"primarybuffer_create() failed
\n
"
);
}
}
else
{
IDirectSoundBufferImpl
*
dsb
;
WAVEFORMATEXTENSIBLE
*
pwfxe
;
/* COM aggregation supported only internally */
if
(
outer_unk
)
obj
->
outer_unk
=
outer_unk
;
else
obj
->
outer_unk
=
&
obj
->
IUnknown_inner
;
if
(
dsbd
->
lpwfxFormat
==
NULL
)
{
WARN
(
"invalid parameter: dsbd->lpwfxFormat can't be NULL for "
"secondary buffer
\n
"
);
return
DSERR_INVALIDPARAM
;
}
pwfxe
=
(
WAVEFORMATEXTENSIBLE
*
)
dsbd
->
lpwfxFormat
;
hr
=
IUnknown_QueryInterface
(
&
obj
->
IUnknown_inner
,
riid
,
ppv
);
IUnknown_Release
(
&
obj
->
IUnknown_inner
);
if
(
pwfxe
->
Format
.
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
)
{
/* check if cbSize is at least 22 bytes */
if
(
pwfxe
->
Format
.
cbSize
<
(
sizeof
(
WAVEFORMATEXTENSIBLE
)
-
sizeof
(
WAVEFORMATEX
)))
{
WARN
(
"Too small a cbSize %u
\n
"
,
pwfxe
->
Format
.
cbSize
);
return
DSERR_INVALIDPARAM
;
}
return
hr
;
}
/* cbSize should be 22 bytes, with one possible exception */
if
(
pwfxe
->
Format
.
cbSize
>
(
sizeof
(
WAVEFORMATEXTENSIBLE
)
-
sizeof
(
WAVEFORMATEX
))
&&
!
((
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_PCM
)
||
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
&&
pwfxe
->
Format
.
cbSize
==
sizeof
(
WAVEFORMATEXTENSIBLE
)))
{
WARN
(
"Too big a cbSize %u
\n
"
,
pwfxe
->
Format
.
cbSize
);
return
DSERR_CONTROLUNAVAIL
;
}
HRESULT
DSOUND_Create
(
REFIID
riid
,
void
**
ppv
)
{
return
IDirectSoundImpl_Create
(
NULL
,
riid
,
ppv
,
FALSE
);
}
if
((
!
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_PCM
))
&&
(
!
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)))
{
if
(
!
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
GUID_NULL
))
FIXME
(
"SubFormat %s not supported right now.
\n
"
,
debugstr_guid
(
&
pwfxe
->
SubFormat
));
return
DSERR_INVALIDPARAM
;
}
if
(
pwfxe
->
Samples
.
wValidBitsPerSample
>
dsbd
->
lpwfxFormat
->
wBitsPerSample
)
{
WARN
(
"Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)
\n
"
,
pwfxe
->
Samples
.
wValidBitsPerSample
,
pwfxe
->
Format
.
wBitsPerSample
);
return
DSERR_INVALIDPARAM
;
}
if
(
pwfxe
->
Samples
.
wValidBitsPerSample
&&
pwfxe
->
Samples
.
wValidBitsPerSample
<
dsbd
->
lpwfxFormat
->
wBitsPerSample
)
{
FIXME
(
"Non-packed formats not supported right now: %d/%d
\n
"
,
pwfxe
->
Samples
.
wValidBitsPerSample
,
dsbd
->
lpwfxFormat
->
wBitsPerSample
);
return
DSERR_CONTROLUNAVAIL
;
}
}
HRESULT
DSOUND_Create8
(
REFIID
riid
,
void
**
ppv
)
{
return
IDirectSoundImpl_Create
(
NULL
,
riid
,
ppv
,
TRUE
);
TRACE
(
"(formattag=0x%04x,chans=%d,samplerate=%d,"
"bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)
\n
"
,
dsbd
->
lpwfxFormat
->
wFormatTag
,
dsbd
->
lpwfxFormat
->
nChannels
,
dsbd
->
lpwfxFormat
->
nSamplesPerSec
,
dsbd
->
lpwfxFormat
->
nAvgBytesPerSec
,
dsbd
->
lpwfxFormat
->
nBlockAlign
,
dsbd
->
lpwfxFormat
->
wBitsPerSample
,
dsbd
->
lpwfxFormat
->
cbSize
);
if
(
from8
&&
(
dsbd
->
dwFlags
&
DSBCAPS_CTRL3D
)
&&
(
dsbd
->
lpwfxFormat
->
nChannels
!=
1
))
{
WARN
(
"invalid parameter: 3D buffer format must be mono
\n
"
);
return
DSERR_INVALIDPARAM
;
}
hres
=
IDirectSoundBufferImpl_Create
(
device
,
&
dsb
,
dsbd
);
if
(
dsb
)
{
*
ppdsb
=
(
IDirectSoundBuffer
*
)
&
dsb
->
IDirectSoundBuffer8_iface
;
if
(
dsbd
->
dwFlags
&
DSBCAPS_LOCHARDWARE
)
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
--
;
}
else
WARN
(
"IDirectSoundBufferImpl_Create failed
\n
"
);
}
return
hres
;
}
/*******************************************************************************
* DirectSoundCreate (DSOUND.1)
*
* Creates and initializes a DirectSound interface.
*
* PARAMS
* lpcGUID [I] Address of the GUID that identifies the sound device.
* ppDS [O] Address of a variable to receive the interface pointer.
* pUnkOuter [I] Must be NULL.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
* DSERR_NODRIVER, DSERR_OUTOFMEMORY
*/
HRESULT
WINAPI
DirectSoundCreate
(
LPCGUID
lpcGUID
,
LPDIRECTSOUND
*
ppDS
,
IUnknown
*
pUnkOuter
)
HRESULT
DirectSoundDevice_DuplicateSoundBuffer
(
DirectSoundDevice
*
device
,
LPDIRECTSOUNDBUFFER
psb
,
LPLPDIRECTSOUNDBUFFER
ppdsb
)
{
HRESULT
hr
;
LPDIRECTSOUND
pDS
;
HRESULT
hres
=
DS_OK
;
IDirectSoundBufferImpl
*
dsb
;
TRACE
(
"(%p,%p,%p)
\n
"
,
device
,
psb
,
ppdsb
);
TRACE
(
"(%s,%p,%p)
\n
"
,
debugstr_guid
(
lpcGUID
),
ppDS
,
pUnkOuter
);
if
(
device
==
NULL
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
if
(
p
pDS
==
NULL
)
{
WARN
(
"invalid parameter: p
pDS
== NULL
\n
"
);
if
(
p
sb
==
NULL
)
{
WARN
(
"invalid parameter: p
sb
== NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
if
(
pUnkOuter
!=
NULL
)
{
WARN
(
"invalid parameter: pUnkOuter != NULL
\n
"
);
*
ppDS
=
0
;
if
(
ppdsb
==
NULL
)
{
WARN
(
"invalid parameter: ppdsb == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
hr
=
DSOUND_Create
(
&
IID_IDirectSound
,
(
void
**
)
&
pDS
);
if
(
hr
==
DS_OK
)
{
hr
=
IDirectSound_Initialize
(
pDS
,
lpcGUID
);
if
(
hr
!=
DS_OK
)
{
if
(
hr
!=
DSERR_ALREADYINITIALIZED
)
{
IDirectSound_Release
(
pDS
);
pDS
=
0
;
}
else
hr
=
DS_OK
;
}
/* make sure we have a secondary buffer */
if
(
psb
==
(
IDirectSoundBuffer
*
)
&
device
->
primary
->
IDirectSoundBuffer8_iface
)
{
WARN
(
"trying to duplicate primary buffer
\n
"
);
*
ppdsb
=
NULL
;
return
DSERR_INVALIDCALL
;
}
*
ppDS
=
pDS
;
/* duplicate the actual buffer implementation */
hres
=
IDirectSoundBufferImpl_Duplicate
(
device
,
&
dsb
,
(
IDirectSoundBufferImpl
*
)
psb
);
if
(
hres
==
DS_OK
)
*
ppdsb
=
(
IDirectSoundBuffer
*
)
&
dsb
->
IDirectSoundBuffer8_iface
;
else
WARN
(
"IDirectSoundBufferImpl_Duplicate failed
\n
"
);
return
hr
;
return
hr
es
;
}
/*******************************************************************************
* DirectSoundCreate8 (DSOUND.11)
*
* Creates and initializes a DirectSound8 interface.
*
* PARAMS
* lpcGUID [I] Address of the GUID that identifies the sound device.
* ppDS [O] Address of a variable to receive the interface pointer.
* pUnkOuter [I] Must be NULL.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
* DSERR_NODRIVER, DSERR_OUTOFMEMORY
/*
* Add secondary buffer to buffer list.
* Gets exclusive access to buffer for writing.
*/
HRESULT
WINAPI
DirectSoundCreate8
(
LPCGUID
lpcGUID
,
LPDIRECTSOUND8
*
ppDS
,
IUnknown
*
pUnkOuter
)
HRESULT
DirectSoundDevice_AddBuffer
(
DirectSoundDevice
*
device
,
IDirectSoundBufferImpl
*
pDSB
)
{
HRESULT
hr
;
LPDIRECTSOUND8
pDS
;
IDirectSoundBufferImpl
**
newbuffers
;
HRESULT
hr
=
DS_OK
;
TRACE
(
"(%
s,%p,%p)
\n
"
,
debugstr_guid
(
lpcGUID
),
ppDS
,
pUnkOuter
);
TRACE
(
"(%
p, %p)
\n
"
,
device
,
pDSB
);
if
(
ppDS
==
NULL
)
{
WARN
(
"invalid parameter: ppDS == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
RtlAcquireResourceExclusive
(
&
(
device
->
buffer_list_lock
),
TRUE
);
if
(
pUnkOuter
!=
NULL
)
{
WARN
(
"invalid parameter: pUnkOuter != NULL
\n
"
);
*
ppDS
=
0
;
return
DSERR_INVALIDPARAM
;
}
if
(
device
->
buffers
)
newbuffers
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
device
->
buffers
,
sizeof
(
IDirectSoundBufferImpl
*
)
*
(
device
->
nrofbuffers
+
1
));
else
newbuffers
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
IDirectSoundBufferImpl
*
)
*
(
device
->
nrofbuffers
+
1
));
hr
=
DSOUND_Create8
(
&
IID_IDirectSound8
,
(
void
**
)
&
pDS
);
if
(
hr
==
DS_OK
)
{
hr
=
IDirectSound8_Initialize
(
pDS
,
lpcGUID
);
if
(
hr
!=
DS_OK
)
{
if
(
hr
!=
DSERR_ALREADYINITIALIZED
)
{
IDirectSound8_Release
(
pDS
);
pDS
=
0
;
}
else
hr
=
DS_OK
;
}
if
(
newbuffers
)
{
device
->
buffers
=
newbuffers
;
device
->
buffers
[
device
->
nrofbuffers
]
=
pDSB
;
device
->
nrofbuffers
++
;
TRACE
(
"buffer count is now %d
\n
"
,
device
->
nrofbuffers
);
}
else
{
ERR
(
"out of memory for buffer list! Current buffer count is %d
\n
"
,
device
->
nrofbuffers
);
hr
=
DSERR_OUTOFMEMORY
;
}
*
ppDS
=
pDS
;
RtlReleaseResource
(
&
(
device
->
buffer_list_lock
))
;
return
hr
;
}
void
DSOUND_ParseSpeakerConfig
(
DirectSoundDevice
*
device
)
/*
* Remove secondary buffer from buffer list.
* Gets exclusive access to buffer for writing.
*/
void
DirectSoundDevice_RemoveBuffer
(
DirectSoundDevice
*
device
,
IDirectSoundBufferImpl
*
pDSB
)
{
switch
(
DSSPEAKER_CONFIG
(
device
->
speaker_config
))
{
case
DSSPEAKER_MONO
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
0
.
0
f
;
device
->
speaker_num
[
0
]
=
0
;
device
->
num_speakers
=
1
;
device
->
lfe_channel
=
-
1
;
break
;
int
i
;
case
DSSPEAKER_STEREO
:
case
DSSPEAKER_HEADPHONE
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
-
90
.
0
f
;
device
->
speaker_angles
[
1
]
=
M_PI
/
180
.
0
f
*
90
.
0
f
;
device
->
speaker_num
[
0
]
=
0
;
/* Left */
device
->
speaker_num
[
1
]
=
1
;
/* Right */
device
->
num_speakers
=
2
;
device
->
lfe_channel
=
-
1
;
break
;
case
DSSPEAKER_QUAD
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
-
135
.
0
f
;
device
->
speaker_angles
[
1
]
=
M_PI
/
180
.
0
f
*
-
45
.
0
f
;
device
->
speaker_angles
[
2
]
=
M_PI
/
180
.
0
f
*
45
.
0
f
;
device
->
speaker_angles
[
3
]
=
M_PI
/
180
.
0
f
*
135
.
0
f
;
device
->
speaker_num
[
0
]
=
2
;
/* Rear left */
device
->
speaker_num
[
1
]
=
0
;
/* Front left */
device
->
speaker_num
[
2
]
=
1
;
/* Front right */
device
->
speaker_num
[
3
]
=
3
;
/* Rear right */
device
->
num_speakers
=
4
;
device
->
lfe_channel
=
-
1
;
break
;
case
DSSPEAKER_5POINT1_BACK
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
-
135
.
0
f
;
device
->
speaker_angles
[
1
]
=
M_PI
/
180
.
0
f
*
-
45
.
0
f
;
device
->
speaker_angles
[
2
]
=
M_PI
/
180
.
0
f
*
0
.
0
f
;
device
->
speaker_angles
[
3
]
=
M_PI
/
180
.
0
f
*
45
.
0
f
;
device
->
speaker_angles
[
4
]
=
M_PI
/
180
.
0
f
*
135
.
0
f
;
device
->
speaker_angles
[
5
]
=
9999
.
0
f
;
device
->
speaker_num
[
0
]
=
4
;
/* Rear left */
device
->
speaker_num
[
1
]
=
0
;
/* Front left */
device
->
speaker_num
[
2
]
=
2
;
/* Front centre */
device
->
speaker_num
[
3
]
=
1
;
/* Front right */
device
->
speaker_num
[
4
]
=
5
;
/* Rear right */
device
->
speaker_num
[
5
]
=
3
;
/* LFE */
device
->
num_speakers
=
6
;
device
->
lfe_channel
=
3
;
break
;
TRACE
(
"(%p, %p)
\n
"
,
device
,
pDSB
);
case
DSSPEAKER_5POINT1_SURROUND
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
-
90
.
0
f
;
device
->
speaker_angles
[
1
]
=
M_PI
/
180
.
0
f
*
-
30
.
0
f
;
device
->
speaker_angles
[
2
]
=
M_PI
/
180
.
0
f
*
0
.
0
f
;
device
->
speaker_angles
[
3
]
=
M_PI
/
180
.
0
f
*
30
.
0
f
;
device
->
speaker_angles
[
4
]
=
M_PI
/
180
.
0
f
*
90
.
0
f
;
device
->
speaker_angles
[
5
]
=
9999
.
0
f
;
device
->
speaker_num
[
0
]
=
4
;
/* Rear left */
device
->
speaker_num
[
1
]
=
0
;
/* Front left */
device
->
speaker_num
[
2
]
=
2
;
/* Front centre */
device
->
speaker_num
[
3
]
=
1
;
/* Front right */
device
->
speaker_num
[
4
]
=
5
;
/* Rear right */
device
->
speaker_num
[
5
]
=
3
;
/* LFE */
device
->
num_speakers
=
6
;
device
->
lfe_channel
=
3
;
break
;
RtlAcquireResourceExclusive
(
&
(
device
->
buffer_list_lock
),
TRUE
);
default:
WARN
(
"unknown speaker_config %u
\n
"
,
device
->
speaker_config
);
if
(
device
->
nrofbuffers
==
1
)
{
assert
(
device
->
buffers
[
0
]
==
pDSB
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
buffers
);
device
->
buffers
=
NULL
;
}
else
{
for
(
i
=
0
;
i
<
device
->
nrofbuffers
;
i
++
)
{
if
(
device
->
buffers
[
i
]
==
pDSB
)
{
/* Put the last buffer of the list in the (now empty) position */
device
->
buffers
[
i
]
=
device
->
buffers
[
device
->
nrofbuffers
-
1
];
break
;
}
}
}
device
->
nrofbuffers
--
;
TRACE
(
"buffer count is now %d
\n
"
,
device
->
nrofbuffers
);
RtlReleaseResource
(
&
(
device
->
buffer_list_lock
));
}
/*******************************************************************************
*
DirectSoundDevice
*
IUnknown Implementation for DirectSound
*/
static
HRESULT
DirectSoundDevice_Create
(
DirectSoundDevice
**
ppDevice
)
{
DirectSoundDevice
*
device
;
TRACE
(
"(%p)
\n
"
,
ppDevice
);
/* Allocate memory */
device
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
DirectSoundDevice
));
if
(
device
==
NULL
)
{
WARN
(
"out of memory
\n
"
);
return
DSERR_OUTOFMEMORY
;
}
static
void
directsound_destroy
(
IDirectSoundImpl
*
This
)
{
if
(
This
->
device
)
DirectSoundDevice_Release
(
This
->
device
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
TRACE
(
"(%p) released
\n
"
,
This
);
}
device
->
ref
=
1
;
device
->
priolevel
=
DSSCL_NORMAL
;
device
->
state
=
STATE_STOPPED
;
device
->
speaker_config
=
DSSPEAKER_COMBINED
(
DSSPEAKER_STEREO
,
DSSPEAKER_GEOMETRY_WIDE
);
static
inline
IDirectSoundImpl
*
impl_from_IUnknown
(
IUnknown
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
IDirectSoundImpl
,
IUnknown_inner
)
;
}
DSOUND_ParseSpeakerConfig
(
device
);
static
HRESULT
WINAPI
IUnknownImpl_QueryInterface
(
IUnknown
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
IDirectSoundImpl
*
This
=
impl_from_IUnknown
(
iface
);
/* 3D listener initial parameters */
device
->
ds3dl
.
dwSize
=
sizeof
(
DS3DLISTENER
);
device
->
ds3dl
.
vPosition
.
x
=
0
.
0
;
device
->
ds3dl
.
vPosition
.
y
=
0
.
0
;
device
->
ds3dl
.
vPosition
.
z
=
0
.
0
;
device
->
ds3dl
.
vVelocity
.
x
=
0
.
0
;
device
->
ds3dl
.
vVelocity
.
y
=
0
.
0
;
device
->
ds3dl
.
vVelocity
.
z
=
0
.
0
;
device
->
ds3dl
.
vOrientFront
.
x
=
0
.
0
;
device
->
ds3dl
.
vOrientFront
.
y
=
0
.
0
;
device
->
ds3dl
.
vOrientFront
.
z
=
1
.
0
;
device
->
ds3dl
.
vOrientTop
.
x
=
0
.
0
;
device
->
ds3dl
.
vOrientTop
.
y
=
1
.
0
;
device
->
ds3dl
.
vOrientTop
.
z
=
0
.
0
;
device
->
ds3dl
.
flDistanceFactor
=
DS3D_DEFAULTDISTANCEFACTOR
;
device
->
ds3dl
.
flRolloffFactor
=
DS3D_DEFAULTROLLOFFFACTOR
;
device
->
ds3dl
.
flDopplerFactor
=
DS3D_DEFAULTDOPPLERFACTOR
;
TRACE
(
"(%p,%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppv
);
device
->
prebuf
=
ds_snd_queue_max
;
device
->
guid
=
GUID_NULL
;
if
(
!
ppv
)
{
WARN
(
"invalid parameter
\n
"
);
return
E_INVALIDARG
;
}
*
ppv
=
NULL
;
/* Set default wave format (may need it for waveOutOpen) */
device
->
pwfx
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
WAVEFORMATEXTENSIBLE
));
device
->
primary_pwfx
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
WAVEFORMATEXTENSIBLE
));
if
(
!
device
->
pwfx
||
!
device
->
primary_pwfx
)
{
WARN
(
"out of memory
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
primary_pwfx
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
pwfx
);
HeapFree
(
GetProcessHeap
(),
0
,
device
);
return
DSERR_OUTOFMEMORY
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
))
*
ppv
=
&
This
->
IUnknown_inner
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IDirectSound
)
||
(
IsEqualIID
(
riid
,
&
IID_IDirectSound8
)
&&
This
->
has_ds8
))
*
ppv
=
&
This
->
IDirectSound8_iface
;
else
{
WARN
(
"unknown IID %s
\n
"
,
debugstr_guid
(
riid
));
return
E_NOINTERFACE
;
}
device
->
pwfx
->
wFormatTag
=
WAVE_FORMAT_PCM
;
device
->
pwfx
->
nSamplesPerSec
=
22050
;
device
->
pwfx
->
wBitsPerSample
=
8
;
device
->
pwfx
->
nChannels
=
2
;
device
->
pwfx
->
nBlockAlign
=
device
->
pwfx
->
wBitsPerSample
*
device
->
pwfx
->
nChannels
/
8
;
device
->
pwfx
->
nAvgBytesPerSec
=
device
->
pwfx
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
cbSize
=
0
;
memcpy
(
device
->
primary_pwfx
,
device
->
pwfx
,
sizeof
(
*
device
->
pwfx
));
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
return
S_OK
;
}
InitializeCriticalSection
(
&
(
device
->
mixlock
));
device
->
mixlock
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": DirectSoundDevice.mixlock"
);
static
ULONG
WINAPI
IUnknownImpl_AddRef
(
IUnknown
*
iface
)
{
IDirectSoundImpl
*
This
=
impl_from_IUnknown
(
iface
);
ULONG
ref
=
InterlockedIncrement
(
&
This
->
ref
);
RtlInitializeResource
(
&
(
device
->
buffer_list_lock
)
);
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
*
ppDevice
=
device
;
if
(
ref
==
1
)
InterlockedIncrement
(
&
This
->
numIfaces
);
return
DS_OK
;
return
ref
;
}
static
ULONG
DirectSoundDevice_AddRef
(
DirectSoundDevice
*
devi
ce
)
static
ULONG
WINAPI
IUnknownImpl_Release
(
IUnknown
*
ifa
ce
)
{
ULONG
ref
=
InterlockedIncrement
(
&
(
device
->
ref
));
TRACE
(
"(%p) ref was %d
\n
"
,
device
,
ref
-
1
);
IDirectSoundImpl
*
This
=
impl_from_IUnknown
(
iface
);
ULONG
ref
=
InterlockedDecrement
(
&
This
->
ref
);
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
if
(
!
ref
&&
!
InterlockedDecrement
(
&
This
->
numIfaces
))
directsound_destroy
(
This
);
return
ref
;
}
ULONG
DirectSoundDevice_Release
(
DirectSoundDevice
*
device
)
static
const
IUnknownVtbl
unk_vtbl
=
{
HRESULT
hr
;
ULONG
ref
=
InterlockedDecrement
(
&
(
device
->
ref
));
TRACE
(
"(%p) ref was %u
\n
"
,
device
,
ref
+
1
);
if
(
!
ref
)
{
int
i
;
IUnknownImpl_QueryInterface
,
IUnknownImpl_AddRef
,
IUnknownImpl_Release
};
SetEvent
(
device
->
sleepev
);
if
(
device
->
thread
)
{
WaitForSingleObject
(
device
->
thread
,
INFINITE
);
CloseHandle
(
device
->
thread
);
}
CloseHandle
(
device
->
sleepev
);
/*******************************************************************************
* IDirectSound and IDirectSound8 Implementation
*/
static
inline
IDirectSoundImpl
*
impl_from_IDirectSound8
(
IDirectSound8
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
IDirectSoundImpl
,
IDirectSound8_iface
);
}
EnterCriticalSection
(
&
DSOUND_renderers_lock
);
list_remove
(
&
device
->
entry
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
static
HRESULT
WINAPI
IDirectSound8Impl_QueryInterface
(
IDirectSound8
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p,%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppv
);
return
IUnknown_QueryInterface
(
This
->
outer_unk
,
riid
,
ppv
);
}
/* It is allowed to release this object even when buffers are playing */
if
(
device
->
buffers
)
{
WARN
(
"%d secondary buffers not released
\n
"
,
device
->
nrofbuffers
);
for
(
i
=
0
;
i
<
device
->
nrofbuffers
;
i
++
)
secondarybuffer_destroy
(
device
->
buffers
[
i
]);
}
static
ULONG
WINAPI
IDirectSound8Impl_AddRef
(
IDirectSound8
*
iface
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
ULONG
ref
=
InterlockedIncrement
(
&
This
->
refds
);
hr
=
DSOUND_PrimaryDestroy
(
device
);
if
(
hr
!=
DS_OK
)
WARN
(
"DSOUND_PrimaryDestroy failed
\n
"
);
TRACE
(
"(%p) refds=%d
\n
"
,
This
,
ref
);
if
(
device
->
client
)
IAudioClient_Release
(
device
->
client
);
if
(
device
->
render
)
IAudioRenderClient_Release
(
device
->
render
);
if
(
device
->
clock
)
IAudioClock_Release
(
device
->
clock
);
if
(
device
->
volume
)
IAudioStreamVolume_Release
(
device
->
volume
);
if
(
ref
==
1
)
InterlockedIncrement
(
&
This
->
numIfaces
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
tmp_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
mix_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
buffer
);
RtlDeleteResource
(
&
device
->
buffer_list_lock
);
device
->
mixlock
.
DebugInfo
->
Spare
[
0
]
=
0
;
DeleteCriticalSection
(
&
device
->
mixlock
);
HeapFree
(
GetProcessHeap
(),
0
,
device
);
TRACE
(
"(%p) released
\n
"
,
device
);
}
return
ref
;
}
BOOL
DSOUND_check_supported
(
IAudioClient
*
client
,
DWORD
rate
,
DWORD
depth
,
WORD
channels
)
static
ULONG
WINAPI
IDirectSound8Impl_Release
(
IDirectSound8
*
iface
)
{
WAVEFORMATEX
fmt
,
*
junk
;
HRESULT
hr
;
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
)
;
ULONG
ref
=
InterlockedDecrement
(
&
(
This
->
refds
))
;
fmt
.
wFormatTag
=
WAVE_FORMAT_PCM
;
fmt
.
nChannels
=
channels
;
fmt
.
nSamplesPerSec
=
rate
;
fmt
.
wBitsPerSample
=
depth
;
fmt
.
nBlockAlign
=
(
channels
*
depth
)
/
8
;
fmt
.
nAvgBytesPerSec
=
rate
*
fmt
.
nBlockAlign
;
fmt
.
cbSize
=
0
;
TRACE
(
"(%p) refds=%d
\n
"
,
This
,
ref
);
hr
=
IAudioClient_IsFormatSupported
(
client
,
AUDCLNT_SHAREMODE_SHARED
,
&
fmt
,
&
junk
);
if
(
SUCCEEDED
(
hr
))
CoTaskMemFree
(
junk
);
if
(
!
ref
&&
!
InterlockedDecrement
(
&
This
->
numIfaces
))
directsound_destroy
(
This
);
return
hr
==
S_OK
;
return
ref
;
}
HRESULT
DirectSoundDevice_Initialize
(
DirectSoundDevice
**
ppDevice
,
LPCGUID
lpcGUID
)
static
HRESULT
WINAPI
IDirectSound8Impl_CreateSoundBuffer
(
IDirectSound8
*
iface
,
const
DSBUFFERDESC
*
dsbd
,
IDirectSoundBuffer
**
ppdsb
,
IUnknown
*
lpunk
)
{
HRESULT
hr
=
DS_OK
;
GUID
devGUID
;
DirectSoundDevice
*
device
;
IMMDevice
*
mmdevice
;
TRACE
(
"(%p,%s)
\n
"
,
ppDevice
,
debugstr_guid
(
lpcGUID
));
if
(
*
ppDevice
!=
NULL
)
{
WARN
(
"already initialized
\n
"
);
return
DSERR_ALREADYINITIALIZED
;
}
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p,%p,%p,%p)
\n
"
,
This
,
dsbd
,
ppdsb
,
lpunk
);
return
DirectSoundDevice_CreateSoundBuffer
(
This
->
device
,
dsbd
,
ppdsb
,
lpunk
,
This
->
has_ds8
);
}
/* Default device? */
if
(
!
lpcGUID
||
IsEqualGUID
(
lpcGUID
,
&
GUID_NULL
))
lpcGUID
=
&
DSDEVID_DefaultPlayback
;
static
HRESULT
WINAPI
IDirectSound8Impl_GetCaps
(
IDirectSound8
*
iface
,
DSCAPS
*
dscaps
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
)
;
if
(
IsEqualGUID
(
lpcGUID
,
&
DSDEVID_DefaultCapture
)
||
IsEqualGUID
(
lpcGUID
,
&
DSDEVID_DefaultVoiceCapture
))
return
DSERR_NODRIVER
;
TRACE
(
"(%p, %p)
\n
"
,
This
,
dscaps
);
if
(
GetDeviceID
(
lpcGUID
,
&
devGUID
)
!=
DS_OK
)
{
WARN
(
"invalid parameter: lpcGUID
\n
"
);
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
if
(
!
dscaps
)
{
WARN
(
"invalid parameter: dscaps = NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
hr
=
get_mmdevice
(
eRender
,
&
devGUID
,
&
mmdevice
);
if
(
FAILED
(
hr
))
return
hr
;
EnterCriticalSection
(
&
DSOUND_renderers_lock
);
LIST_FOR_EACH_ENTRY
(
device
,
&
DSOUND_renderers
,
DirectSoundDevice
,
entry
){
if
(
IsEqualGUID
(
&
device
->
guid
,
&
devGUID
)){
IMMDevice_Release
(
mmdevice
);
DirectSoundDevice_AddRef
(
device
);
*
ppDevice
=
device
;
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
return
DS_OK
;
}
if
(
dscaps
->
dwSize
<
sizeof
(
*
dscaps
))
{
WARN
(
"invalid parameter: dscaps->dwSize = %d
\n
"
,
dscaps
->
dwSize
);
return
DSERR_INVALIDPARAM
;
}
hr
=
DirectSoundDevice_Create
(
&
device
);
if
(
FAILED
(
hr
)){
WARN
(
"DirectSoundDevice_Create failed
\n
"
);
IMMDevice_Release
(
mmdevice
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
return
hr
;
dscaps
->
dwFlags
=
This
->
device
->
drvcaps
.
dwFlags
;
dscaps
->
dwMinSecondarySampleRate
=
This
->
device
->
drvcaps
.
dwMinSecondarySampleRate
;
dscaps
->
dwMaxSecondarySampleRate
=
This
->
device
->
drvcaps
.
dwMaxSecondarySampleRate
;
dscaps
->
dwPrimaryBuffers
=
This
->
device
->
drvcaps
.
dwPrimaryBuffers
;
dscaps
->
dwMaxHwMixingAllBuffers
=
This
->
device
->
drvcaps
.
dwMaxHwMixingAllBuffers
;
dscaps
->
dwMaxHwMixingStaticBuffers
=
This
->
device
->
drvcaps
.
dwMaxHwMixingStaticBuffers
;
dscaps
->
dwMaxHwMixingStreamingBuffers
=
This
->
device
->
drvcaps
.
dwMaxHwMixingStreamingBuffers
;
dscaps
->
dwFreeHwMixingAllBuffers
=
This
->
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
;
if
(
This
->
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
>
0
)
{
dscaps
->
dwFreeHwMixingStaticBuffers
=
This
->
device
->
drvcaps
.
dwFreeHwMixingStaticBuffers
;
dscaps
->
dwFreeHwMixingStreamingBuffers
=
This
->
device
->
drvcaps
.
dwFreeHwMixingStreamingBuffers
;
}
else
{
dscaps
->
dwFreeHwMixingStaticBuffers
=
0
;
dscaps
->
dwFreeHwMixingStreamingBuffers
=
0
;
}
device
->
mmdevice
=
mmdevice
;
device
->
guid
=
devGUID
;
device
->
sleepev
=
CreateEventW
(
0
,
0
,
0
,
0
);
dscaps
->
dwMaxHw3DAllBuffers
=
This
->
device
->
drvcaps
.
dwMaxHw3DAllBuffers
;
dscaps
->
dwMaxHw3DStaticBuffers
=
This
->
device
->
drvcaps
.
dwMaxHw3DStaticBuffers
;
dscaps
->
dwMaxHw3DStreamingBuffers
=
This
->
device
->
drvcaps
.
dwMaxHw3DStreamingBuffers
;
dscaps
->
dwFreeHw3DAllBuffers
=
This
->
device
->
drvcaps
.
dwFreeHw3DAllBuffers
;
dscaps
->
dwFreeHw3DStaticBuffers
=
This
->
device
->
drvcaps
.
dwFreeHw3DStaticBuffers
;
dscaps
->
dwFreeHw3DStreamingBuffers
=
This
->
device
->
drvcaps
.
dwFreeHw3DStreamingBuffers
;
dscaps
->
dwTotalHwMemBytes
=
This
->
device
->
drvcaps
.
dwTotalHwMemBytes
;
dscaps
->
dwFreeHwMemBytes
=
This
->
device
->
drvcaps
.
dwFreeHwMemBytes
;
dscaps
->
dwMaxContigFreeHwMemBytes
=
This
->
device
->
drvcaps
.
dwMaxContigFreeHwMemBytes
;
dscaps
->
dwUnlockTransferRateHwBuffers
=
This
->
device
->
drvcaps
.
dwUnlockTransferRateHwBuffers
;
dscaps
->
dwPlayCpuOverheadSwBuffers
=
This
->
device
->
drvcaps
.
dwPlayCpuOverheadSwBuffers
;
hr
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
FAILED
(
hr
))
{
HeapFree
(
GetProcessHeap
(),
0
,
device
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
IMMDevice_Release
(
mmdevice
);
WARN
(
"DSOUND_ReopenDevice failed: %08x
\n
"
,
hr
);
return
hr
;
if
(
TRACE_ON
(
dsound
))
{
TRACE
(
"(flags=0x%08x:
\n
"
,
dscaps
->
dwFlags
);
_dump_DSCAPS
(
dscaps
->
dwFlags
);
TRACE
(
")
\n
"
);
}
ZeroMemory
(
&
device
->
drvcaps
,
sizeof
(
device
->
drvcaps
));
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
8
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
8
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
8
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
8
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
8
,
1
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY8BIT
|
DSCAPS_PRIMARYMONO
;
return
DS_OK
;
}
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
16
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
16
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
16
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
16
,
1
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
16
,
1
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY16BIT
|
DSCAPS_PRIMARYMONO
;
static
HRESULT
WINAPI
IDirectSound8Impl_DuplicateSoundBuffer
(
IDirectSound8
*
iface
,
IDirectSoundBuffer
*
psb
,
IDirectSoundBuffer
**
ppdsb
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p,%p,%p)
\n
"
,
This
,
psb
,
ppdsb
);
return
DirectSoundDevice_DuplicateSoundBuffer
(
This
->
device
,
psb
,
ppdsb
);
}
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
8
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
8
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
8
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
8
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
8
,
2
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY8BIT
|
DSCAPS_PRIMARYSTEREO
;
static
HRESULT
WINAPI
IDirectSound8Impl_SetCooperativeLevel
(
IDirectSound8
*
iface
,
HWND
hwnd
,
DWORD
level
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
DirectSoundDevice
*
device
=
This
->
device
;
DWORD
oldlevel
;
HRESULT
hr
=
S_OK
;
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
16
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
16
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
16
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
16
,
2
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
16
,
2
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY16BIT
|
DSCAPS_PRIMARYSTEREO
;
TRACE
(
"(%p,%p,%s)
\n
"
,
This
,
hwnd
,
dumpCooperativeLevel
(
level
));
/* the dsound mixer supports all of the following */
device
->
drvcaps
.
dwFlags
|=
DSCAPS_SECONDARY8BIT
|
DSCAPS_SECONDARY16BIT
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_SECONDARYMONO
|
DSCAPS_SECONDARYSTEREO
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_CONTINUOUSRATE
;
if
(
!
device
)
{
WARN
(
"not initialized
\n
"
)
;
return
DSERR_UNINITIALIZED
;
}
device
->
drvcaps
.
dwPrimaryBuffers
=
1
;
device
->
drvcaps
.
dwMinSecondarySampleRate
=
DSBFREQUENCY_MIN
;
device
->
drvcaps
.
dwMaxSecondarySampleRate
=
DSBFREQUENCY_MAX
;
device
->
drvcaps
.
dwMaxHwMixingAllBuffers
=
16
;
device
->
drvcaps
.
dwMaxHwMixingStaticBuffers
=
1
;
device
->
drvcaps
.
dwMaxHwMixingStreamingBuffers
=
1
;
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
=
device
->
drvcaps
.
dwMaxHwMixingAllBuffers
;
device
->
drvcaps
.
dwFreeHwMixingStaticBuffers
=
device
->
drvcaps
.
dwMaxHwMixingStaticBuffers
;
device
->
drvcaps
.
dwFreeHwMixingStreamingBuffers
=
device
->
drvcaps
.
dwMaxHwMixingStreamingBuffers
;
if
(
level
==
DSSCL_PRIORITY
||
level
==
DSSCL_EXCLUSIVE
)
{
WARN
(
"level=%s not fully supported
\n
"
,
level
==
DSSCL_PRIORITY
?
"DSSCL_PRIORITY"
:
"DSSCL_EXCLUSIVE"
);
}
ZeroMemory
(
&
device
->
volpan
,
sizeof
(
device
->
volpan
));
RtlAcquireResourceExclusive
(
&
device
->
buffer_list_lock
,
TRUE
);
EnterCriticalSection
(
&
device
->
mixlock
);
oldlevel
=
device
->
priolevel
;
device
->
priolevel
=
level
;
if
((
level
==
DSSCL_WRITEPRIMARY
)
!=
(
oldlevel
==
DSSCL_WRITEPRIMARY
))
{
hr
=
DSOUND_ReopenDevice
(
device
,
level
==
DSSCL_WRITEPRIMARY
);
if
(
FAILED
(
hr
))
device
->
priolevel
=
oldlevel
;
else
DSOUND_PrimaryOpen
(
device
);
}
LeaveCriticalSection
(
&
device
->
mixlock
);
RtlReleaseResource
(
&
device
->
buffer_list_lock
);
return
hr
;
}
hr
=
DSOUND_PrimaryCreate
(
device
);
if
(
hr
==
DS_OK
)
{
device
->
thread
=
CreateThread
(
0
,
0
,
DSOUND_mixthread
,
device
,
0
,
0
);
SetThreadPriority
(
device
->
thread
,
THREAD_PRIORITY_TIME_CRITICAL
);
}
else
WARN
(
"DSOUND_PrimaryCreate failed: %08x
\n
"
,
hr
);
static
HRESULT
WINAPI
IDirectSound8Impl_Compact
(
IDirectSound8
*
iface
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
*
ppDevice
=
device
;
list_add_tail
(
&
DSOUND_renderers
,
&
device
->
entry
);
TRACE
(
"(%p)
\n
"
,
This
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
return
hr
;
if
(
This
->
device
->
priolevel
<
DSSCL_PRIORITY
)
{
WARN
(
"incorrect priority level
\n
"
);
return
DSERR_PRIOLEVELNEEDED
;
}
return
DS_OK
;
}
HRESULT
DirectSoundDevice_CreateSoundBuffer
(
DirectSoundDevice
*
device
,
LPCDSBUFFERDESC
dsbd
,
LPLPDIRECTSOUNDBUFFER
ppdsb
,
LPUNKNOWN
lpunk
,
BOOL
from8
)
static
HRESULT
WINAPI
IDirectSound8Impl_GetSpeakerConfig
(
IDirectSound8
*
iface
,
DWORD
*
config
)
{
HRESULT
hres
=
DS_OK
;
TRACE
(
"(%p,%p,%p,%p)
\n
"
,
device
,
dsbd
,
ppdsb
,
lpunk
);
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
if
(
device
==
NULL
)
{
TRACE
(
"(%p, %p)
\n
"
,
This
,
config
);
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
if
(
dsbd
==
NULL
)
{
WARN
(
"invalid parameter: dsbd == NULL
\n
"
);
if
(
!
config
)
{
WARN
(
"invalid parameter: config == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
if
(
dsbd
->
dwSize
!=
sizeof
(
DSBUFFERDESC
)
&&
dsbd
->
dwSize
!=
sizeof
(
DSBUFFERDESC1
))
{
WARN
(
"invalid parameter: dsbd
\n
"
);
return
DSERR_INVALIDPARAM
;
}
WARN
(
"not fully functional
\n
"
);
*
config
=
This
->
device
->
speaker_config
;
return
DS_OK
;
}
if
(
ppdsb
==
NULL
)
{
WARN
(
"invalid parameter: ppdsb == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
*
ppdsb
=
NULL
;
static
HRESULT
WINAPI
IDirectSound8Impl_SetSpeakerConfig
(
IDirectSound8
*
iface
,
DWORD
config
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
if
(
TRACE_ON
(
dsound
))
{
TRACE
(
"(structsize=%d)
\n
"
,
dsbd
->
dwSize
);
TRACE
(
"(flags=0x%08x:
\n
"
,
dsbd
->
dwFlags
);
_dump_DSBCAPS
(
dsbd
->
dwFlags
);
TRACE
(
")
\n
"
);
TRACE
(
"(bufferbytes=%d)
\n
"
,
dsbd
->
dwBufferBytes
);
TRACE
(
"(lpwfxFormat=%p)
\n
"
,
dsbd
->
lpwfxFormat
);
TRACE
(
"(%p,0x%08x)
\n
"
,
This
,
config
);
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
if
(
!
(
dsbd
->
dwFlags
&
DSBCAPS_PRIMARYBUFFER
)
&&
dsbd
->
dwFlags
&
DSBCAPS_LOCHARDWARE
&&
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
==
0
)
{
WARN
(
"ran out of emulated hardware buffers
\n
"
);
return
DSERR_ALLOCATED
;
/* NOP on Vista and above */
return
DS_OK
;
}
static
HRESULT
WINAPI
IDirectSound8Impl_Initialize
(
IDirectSound8
*
iface
,
const
GUID
*
lpcGuid
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p, %s)
\n
"
,
This
,
debugstr_guid
(
lpcGuid
));
return
DirectSoundDevice_Initialize
(
&
This
->
device
,
lpcGuid
);
}
static
HRESULT
WINAPI
IDirectSound8Impl_VerifyCertification
(
IDirectSound8
*
iface
,
DWORD
*
certified
)
{
IDirectSoundImpl
*
This
=
impl_from_IDirectSound8
(
iface
);
TRACE
(
"(%p, %p)
\n
"
,
This
,
certified
);
if
(
!
This
->
device
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
if
(
dsbd
->
dwFlags
&
DSBCAPS_PRIMARYBUFFER
)
{
if
(
dsbd
->
lpwfxFormat
!=
NULL
)
{
WARN
(
"invalid parameter: dsbd->lpwfxFormat must be NULL for "
"primary buffer
\n
"
);
return
DSERR_INVALIDPARAM
;
}
if
(
This
->
device
->
drvcaps
.
dwFlags
&
DSCAPS_CERTIFIED
)
*
certified
=
DS_CERTIFIED
;
else
*
certified
=
DS_UNCERTIFIED
;
if
(
device
->
primary
)
{
WARN
(
"Primary Buffer already created
\n
"
);
IDirectSoundBuffer_AddRef
((
LPDIRECTSOUNDBUFFER8
)(
device
->
primary
));
*
ppdsb
=
(
LPDIRECTSOUNDBUFFER
)(
device
->
primary
);
}
else
{
hres
=
primarybuffer_create
(
device
,
&
device
->
primary
,
dsbd
);
if
(
device
->
primary
)
{
*
ppdsb
=
(
IDirectSoundBuffer
*
)
&
device
->
primary
->
IDirectSoundBuffer8_iface
;
device
->
primary
->
dsbd
.
dwFlags
&=
~
(
DSBCAPS_LOCHARDWARE
|
DSBCAPS_LOCSOFTWARE
);
device
->
primary
->
dsbd
.
dwFlags
|=
DSBCAPS_LOCSOFTWARE
;
}
else
WARN
(
"primarybuffer_create() failed
\n
"
);
}
}
else
{
IDirectSoundBufferImpl
*
dsb
;
WAVEFORMATEXTENSIBLE
*
pwfxe
;
return
DS_OK
;
}
if
(
dsbd
->
lpwfxFormat
==
NULL
)
{
WARN
(
"invalid parameter: dsbd->lpwfxFormat can't be NULL for "
"secondary buffer
\n
"
);
return
DSERR_INVALIDPARAM
;
}
pwfxe
=
(
WAVEFORMATEXTENSIBLE
*
)
dsbd
->
lpwfxFormat
;
static
const
IDirectSound8Vtbl
ds8_vtbl
=
{
IDirectSound8Impl_QueryInterface
,
IDirectSound8Impl_AddRef
,
IDirectSound8Impl_Release
,
IDirectSound8Impl_CreateSoundBuffer
,
IDirectSound8Impl_GetCaps
,
IDirectSound8Impl_DuplicateSoundBuffer
,
IDirectSound8Impl_SetCooperativeLevel
,
IDirectSound8Impl_Compact
,
IDirectSound8Impl_GetSpeakerConfig
,
IDirectSound8Impl_SetSpeakerConfig
,
IDirectSound8Impl_Initialize
,
IDirectSound8Impl_VerifyCertification
};
if
(
pwfxe
->
Format
.
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
)
{
/* check if cbSize is at least 22 bytes */
if
(
pwfxe
->
Format
.
cbSize
<
(
sizeof
(
WAVEFORMATEXTENSIBLE
)
-
sizeof
(
WAVEFORMATEX
)))
{
WARN
(
"Too small a cbSize %u
\n
"
,
pwfxe
->
Format
.
cbSize
);
return
DSERR_INVALIDPARAM
;
}
HRESULT
IDirectSoundImpl_Create
(
IUnknown
*
outer_unk
,
REFIID
riid
,
void
**
ppv
,
BOOL
has_ds8
)
{
IDirectSoundImpl
*
obj
;
HRESULT
hr
;
/* cbSize should be 22 bytes, with one possible exception */
if
(
pwfxe
->
Format
.
cbSize
>
(
sizeof
(
WAVEFORMATEXTENSIBLE
)
-
sizeof
(
WAVEFORMATEX
))
&&
!
((
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_PCM
)
||
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
&&
pwfxe
->
Format
.
cbSize
==
sizeof
(
WAVEFORMATEXTENSIBLE
)))
{
WARN
(
"Too big a cbSize %u
\n
"
,
pwfxe
->
Format
.
cbSize
);
return
DSERR_CONTROLUNAVAIL
;
}
TRACE
(
"(%s, %p)
\n
"
,
debugstr_guid
(
riid
),
ppv
);
if
((
!
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_PCM
))
&&
(
!
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)))
{
if
(
!
IsEqualGUID
(
&
pwfxe
->
SubFormat
,
&
GUID_NULL
))
FIXME
(
"SubFormat %s not supported right now.
\n
"
,
debugstr_guid
(
&
pwfxe
->
SubFormat
));
return
DSERR_INVALIDPARAM
;
}
if
(
pwfxe
->
Samples
.
wValidBitsPerSample
>
dsbd
->
lpwfxFormat
->
wBitsPerSample
)
{
WARN
(
"Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)
\n
"
,
pwfxe
->
Samples
.
wValidBitsPerSample
,
pwfxe
->
Format
.
wBitsPerSample
);
return
DSERR_INVALIDPARAM
;
}
if
(
pwfxe
->
Samples
.
wValidBitsPerSample
&&
pwfxe
->
Samples
.
wValidBitsPerSample
<
dsbd
->
lpwfxFormat
->
wBitsPerSample
)
{
FIXME
(
"Non-packed formats not supported right now: %d/%d
\n
"
,
pwfxe
->
Samples
.
wValidBitsPerSample
,
dsbd
->
lpwfxFormat
->
wBitsPerSample
);
return
DSERR_CONTROLUNAVAIL
;
}
}
*
ppv
=
NULL
;
obj
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
*
obj
));
if
(
!
obj
)
{
WARN
(
"out of memory
\n
"
);
return
DSERR_OUTOFMEMORY
;
}
setup_dsound_options
();
obj
->
IUnknown_inner
.
lpVtbl
=
&
unk_vtbl
;
obj
->
IDirectSound8_iface
.
lpVtbl
=
&
ds8_vtbl
;
obj
->
ref
=
1
;
obj
->
refds
=
0
;
obj
->
numIfaces
=
1
;
obj
->
device
=
NULL
;
obj
->
has_ds8
=
has_ds8
;
TRACE
(
"(formattag=0x%04x,chans=%d,samplerate=%d,"
"bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)
\n
"
,
dsbd
->
lpwfxFormat
->
wFormatTag
,
dsbd
->
lpwfxFormat
->
nChannels
,
dsbd
->
lpwfxFormat
->
nSamplesPerSec
,
dsbd
->
lpwfxFormat
->
nAvgBytesPerSec
,
dsbd
->
lpwfxFormat
->
nBlockAlign
,
dsbd
->
lpwfxFormat
->
wBitsPerSample
,
dsbd
->
lpwfxFormat
->
cbSize
);
/* COM aggregation supported only internally */
if
(
outer_unk
)
obj
->
outer_unk
=
outer_unk
;
else
obj
->
outer_unk
=
&
obj
->
IUnknown_inner
;
if
(
from8
&&
(
dsbd
->
dwFlags
&
DSBCAPS_CTRL3D
)
&&
(
dsbd
->
lpwfxFormat
->
nChannels
!=
1
))
{
WARN
(
"invalid parameter: 3D buffer format must be mono
\n
"
);
return
DSERR_INVALIDPARAM
;
}
hr
=
IUnknown_QueryInterface
(
&
obj
->
IUnknown_inner
,
riid
,
ppv
);
IUnknown_Release
(
&
obj
->
IUnknown_inner
);
hres
=
IDirectSoundBufferImpl_Create
(
device
,
&
dsb
,
dsbd
);
if
(
dsb
)
{
*
ppdsb
=
(
IDirectSoundBuffer
*
)
&
dsb
->
IDirectSoundBuffer8_iface
;
if
(
dsbd
->
dwFlags
&
DSBCAPS_LOCHARDWARE
)
device
->
drvcaps
.
dwFreeHwMixingAllBuffers
--
;
}
else
WARN
(
"IDirectSoundBufferImpl_Create failed
\n
"
);
}
return
hr
;
}
return
hres
;
HRESULT
DSOUND_Create
(
REFIID
riid
,
void
**
ppv
)
{
return
IDirectSoundImpl_Create
(
NULL
,
riid
,
ppv
,
FALSE
);
}
HRESULT
DirectSoundDevice_DuplicateSoundBuffer
(
DirectSoundDevice
*
device
,
LPDIRECTSOUNDBUFFER
psb
,
LPLPDIRECTSOUNDBUFFER
ppdsb
)
HRESULT
DSOUND_Create8
(
REFIID
riid
,
void
**
ppv
)
{
HRESULT
hres
=
DS_OK
;
IDirectSoundBufferImpl
*
dsb
;
TRACE
(
"(%p,%p,%p)
\n
"
,
device
,
psb
,
ppdsb
);
return
IDirectSoundImpl_Create
(
NULL
,
riid
,
ppv
,
TRUE
);
}
if
(
device
==
NULL
)
{
WARN
(
"not initialized
\n
"
);
return
DSERR_UNINITIALIZED
;
}
/*******************************************************************************
* DirectSoundCreate (DSOUND.1)
*
* Creates and initializes a DirectSound interface.
*
* PARAMS
* lpcGUID [I] Address of the GUID that identifies the sound device.
* ppDS [O] Address of a variable to receive the interface pointer.
* pUnkOuter [I] Must be NULL.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
* DSERR_NODRIVER, DSERR_OUTOFMEMORY
*/
HRESULT
WINAPI
DirectSoundCreate
(
LPCGUID
lpcGUID
,
LPDIRECTSOUND
*
ppDS
,
IUnknown
*
pUnkOuter
)
{
HRESULT
hr
;
LPDIRECTSOUND
pDS
;
if
(
psb
==
NULL
)
{
WARN
(
"invalid parameter: psb == NULL
\n
"
);
TRACE
(
"(%s,%p,%p)
\n
"
,
debugstr_guid
(
lpcGUID
),
ppDS
,
pUnkOuter
);
if
(
ppDS
==
NULL
)
{
WARN
(
"invalid parameter: ppDS == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
if
(
ppdsb
==
NULL
)
{
WARN
(
"invalid parameter: ppdsb == NULL
\n
"
);
if
(
pUnkOuter
!=
NULL
)
{
WARN
(
"invalid parameter: pUnkOuter != NULL
\n
"
);
*
ppDS
=
0
;
return
DSERR_INVALIDPARAM
;
}
/* make sure we have a secondary buffer */
if
(
psb
==
(
IDirectSoundBuffer
*
)
&
device
->
primary
->
IDirectSoundBuffer8_iface
)
{
WARN
(
"trying to duplicate primary buffer
\n
"
);
*
ppdsb
=
NULL
;
return
DSERR_INVALIDCALL
;
hr
=
DSOUND_Create
(
&
IID_IDirectSound
,
(
void
**
)
&
pDS
);
if
(
hr
==
DS_OK
)
{
hr
=
IDirectSound_Initialize
(
pDS
,
lpcGUID
);
if
(
hr
!=
DS_OK
)
{
if
(
hr
!=
DSERR_ALREADYINITIALIZED
)
{
IDirectSound_Release
(
pDS
);
pDS
=
0
;
}
else
hr
=
DS_OK
;
}
}
/* duplicate the actual buffer implementation */
hres
=
IDirectSoundBufferImpl_Duplicate
(
device
,
&
dsb
,
(
IDirectSoundBufferImpl
*
)
psb
);
if
(
hres
==
DS_OK
)
*
ppdsb
=
(
IDirectSoundBuffer
*
)
&
dsb
->
IDirectSoundBuffer8_iface
;
else
WARN
(
"IDirectSoundBufferImpl_Duplicate failed
\n
"
);
*
ppDS
=
pDS
;
return
hr
es
;
return
hr
;
}
/*
* Add secondary buffer to buffer list.
* Gets exclusive access to buffer for writing.
/*******************************************************************************
* DirectSoundCreate8 (DSOUND.11)
*
* Creates and initializes a DirectSound8 interface.
*
* PARAMS
* lpcGUID [I] Address of the GUID that identifies the sound device.
* ppDS [O] Address of a variable to receive the interface pointer.
* pUnkOuter [I] Must be NULL.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
* DSERR_NODRIVER, DSERR_OUTOFMEMORY
*/
HRESULT
DirectSoundDevice_AddBuffer
(
DirectSoundDevice
*
device
,
IDirectSoundBufferImpl
*
pDSB
)
HRESULT
WINAPI
DirectSoundCreate8
(
LPCGUID
lpcGUID
,
LPDIRECTSOUND8
*
ppDS
,
IUnknown
*
pUnkOuter
)
{
IDirectSoundBufferImpl
**
newbuffers
;
HRESULT
hr
=
DS_OK
;
HRESULT
hr
;
LPDIRECTSOUND8
pDS
;
TRACE
(
"(%
p, %p)
\n
"
,
device
,
pDSB
);
TRACE
(
"(%
s,%p,%p)
\n
"
,
debugstr_guid
(
lpcGUID
),
ppDS
,
pUnkOuter
);
RtlAcquireResourceExclusive
(
&
(
device
->
buffer_list_lock
),
TRUE
);
if
(
ppDS
==
NULL
)
{
WARN
(
"invalid parameter: ppDS == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
}
if
(
device
->
buffers
)
newbuffers
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
device
->
buffers
,
sizeof
(
IDirectSoundBufferImpl
*
)
*
(
device
->
nrofbuffers
+
1
));
else
newbuffers
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
IDirectSoundBufferImpl
*
)
*
(
device
->
nrofbuffers
+
1
));
if
(
pUnkOuter
!=
NULL
)
{
WARN
(
"invalid parameter: pUnkOuter != NULL
\n
"
);
*
ppDS
=
0
;
return
DSERR_INVALIDPARAM
;
}
if
(
newbuffers
)
{
device
->
buffers
=
newbuffers
;
device
->
buffers
[
device
->
nrofbuffers
]
=
pDSB
;
device
->
nrofbuffers
++
;
TRACE
(
"buffer count is now %d
\n
"
,
device
->
nrofbuffers
);
}
else
{
ERR
(
"out of memory for buffer list! Current buffer count is %d
\n
"
,
device
->
nrofbuffers
);
hr
=
DSERR_OUTOFMEMORY
;
hr
=
DSOUND_Create8
(
&
IID_IDirectSound8
,
(
void
**
)
&
pDS
);
if
(
hr
==
DS_OK
)
{
hr
=
IDirectSound8_Initialize
(
pDS
,
lpcGUID
);
if
(
hr
!=
DS_OK
)
{
if
(
hr
!=
DSERR_ALREADYINITIALIZED
)
{
IDirectSound8_Release
(
pDS
);
pDS
=
0
;
}
else
hr
=
DS_OK
;
}
}
RtlReleaseResource
(
&
(
device
->
buffer_list_lock
))
;
*
ppDS
=
pDS
;
return
hr
;
}
/*
* Remove secondary buffer from buffer list.
* Gets exclusive access to buffer for writing.
*/
void
DirectSoundDevice_RemoveBuffer
(
DirectSoundDevice
*
device
,
IDirectSoundBufferImpl
*
pDSB
)
void
DSOUND_ParseSpeakerConfig
(
DirectSoundDevice
*
device
)
{
int
i
;
switch
(
DSSPEAKER_CONFIG
(
device
->
speaker_config
))
{
case
DSSPEAKER_MONO
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
0
.
0
f
;
device
->
speaker_num
[
0
]
=
0
;
device
->
num_speakers
=
1
;
device
->
lfe_channel
=
-
1
;
break
;
TRACE
(
"(%p, %p)
\n
"
,
device
,
pDSB
);
case
DSSPEAKER_STEREO
:
case
DSSPEAKER_HEADPHONE
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
-
90
.
0
f
;
device
->
speaker_angles
[
1
]
=
M_PI
/
180
.
0
f
*
90
.
0
f
;
device
->
speaker_num
[
0
]
=
0
;
/* Left */
device
->
speaker_num
[
1
]
=
1
;
/* Right */
device
->
num_speakers
=
2
;
device
->
lfe_channel
=
-
1
;
break
;
RtlAcquireResourceExclusive
(
&
(
device
->
buffer_list_lock
),
TRUE
);
case
DSSPEAKER_QUAD
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
-
135
.
0
f
;
device
->
speaker_angles
[
1
]
=
M_PI
/
180
.
0
f
*
-
45
.
0
f
;
device
->
speaker_angles
[
2
]
=
M_PI
/
180
.
0
f
*
45
.
0
f
;
device
->
speaker_angles
[
3
]
=
M_PI
/
180
.
0
f
*
135
.
0
f
;
device
->
speaker_num
[
0
]
=
2
;
/* Rear left */
device
->
speaker_num
[
1
]
=
0
;
/* Front left */
device
->
speaker_num
[
2
]
=
1
;
/* Front right */
device
->
speaker_num
[
3
]
=
3
;
/* Rear right */
device
->
num_speakers
=
4
;
device
->
lfe_channel
=
-
1
;
break
;
if
(
device
->
nrofbuffers
==
1
)
{
assert
(
device
->
buffers
[
0
]
==
pDSB
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
buffers
);
device
->
buffers
=
NULL
;
}
else
{
for
(
i
=
0
;
i
<
device
->
nrofbuffers
;
i
++
)
{
if
(
device
->
buffers
[
i
]
==
pDSB
)
{
/* Put the last buffer of the list in the (now empty) position */
device
->
buffers
[
i
]
=
device
->
buffers
[
device
->
nrofbuffers
-
1
];
break
;
}
}
}
device
->
nrofbuffers
--
;
TRACE
(
"buffer count is now %d
\n
"
,
device
->
nrofbuffers
);
case
DSSPEAKER_5POINT1_BACK
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
-
135
.
0
f
;
device
->
speaker_angles
[
1
]
=
M_PI
/
180
.
0
f
*
-
45
.
0
f
;
device
->
speaker_angles
[
2
]
=
M_PI
/
180
.
0
f
*
0
.
0
f
;
device
->
speaker_angles
[
3
]
=
M_PI
/
180
.
0
f
*
45
.
0
f
;
device
->
speaker_angles
[
4
]
=
M_PI
/
180
.
0
f
*
135
.
0
f
;
device
->
speaker_angles
[
5
]
=
9999
.
0
f
;
device
->
speaker_num
[
0
]
=
4
;
/* Rear left */
device
->
speaker_num
[
1
]
=
0
;
/* Front left */
device
->
speaker_num
[
2
]
=
2
;
/* Front centre */
device
->
speaker_num
[
3
]
=
1
;
/* Front right */
device
->
speaker_num
[
4
]
=
5
;
/* Rear right */
device
->
speaker_num
[
5
]
=
3
;
/* LFE */
device
->
num_speakers
=
6
;
device
->
lfe_channel
=
3
;
break
;
RtlReleaseResource
(
&
(
device
->
buffer_list_lock
));
case
DSSPEAKER_5POINT1_SURROUND
:
device
->
speaker_angles
[
0
]
=
M_PI
/
180
.
0
f
*
-
90
.
0
f
;
device
->
speaker_angles
[
1
]
=
M_PI
/
180
.
0
f
*
-
30
.
0
f
;
device
->
speaker_angles
[
2
]
=
M_PI
/
180
.
0
f
*
0
.
0
f
;
device
->
speaker_angles
[
3
]
=
M_PI
/
180
.
0
f
*
30
.
0
f
;
device
->
speaker_angles
[
4
]
=
M_PI
/
180
.
0
f
*
90
.
0
f
;
device
->
speaker_angles
[
5
]
=
9999
.
0
f
;
device
->
speaker_num
[
0
]
=
4
;
/* Rear left */
device
->
speaker_num
[
1
]
=
0
;
/* Front left */
device
->
speaker_num
[
2
]
=
2
;
/* Front centre */
device
->
speaker_num
[
3
]
=
1
;
/* Front right */
device
->
speaker_num
[
4
]
=
5
;
/* Rear right */
device
->
speaker_num
[
5
]
=
3
;
/* LFE */
device
->
num_speakers
=
6
;
device
->
lfe_channel
=
3
;
break
;
default:
WARN
(
"unknown speaker_config %u
\n
"
,
device
->
speaker_config
);
}
}
dlls/dsound/dsound_private.h
View file @
dfaef530
...
...
@@ -111,24 +111,10 @@ typedef struct BufferMemory
struct
list
buffers
;
}
BufferMemory
;
ULONG
DirectSoundDevice_Release
(
DirectSoundDevice
*
device
)
DECLSPEC_HIDDEN
;
HRESULT
DirectSoundDevice_Initialize
(
DirectSoundDevice
**
ppDevice
,
LPCGUID
lpcGUID
)
DECLSPEC_HIDDEN
;
HRESULT
DirectSoundDevice_AddBuffer
(
DirectSoundDevice
*
device
,
IDirectSoundBufferImpl
*
pDSB
)
DECLSPEC_HIDDEN
;
void
DirectSoundDevice_RemoveBuffer
(
DirectSoundDevice
*
device
,
IDirectSoundBufferImpl
*
pDSB
)
DECLSPEC_HIDDEN
;
HRESULT
DirectSoundDevice_CreateSoundBuffer
(
DirectSoundDevice
*
device
,
LPCDSBUFFERDESC
dsbd
,
LPLPDIRECTSOUNDBUFFER
ppdsb
,
LPUNKNOWN
lpunk
,
BOOL
from8
)
DECLSPEC_HIDDEN
;
HRESULT
DirectSoundDevice_DuplicateSoundBuffer
(
DirectSoundDevice
*
device
,
LPDIRECTSOUNDBUFFER
psb
,
LPLPDIRECTSOUNDBUFFER
ppdsb
)
DECLSPEC_HIDDEN
;
/*****************************************************************************
* IDirectSoundBuffer implementation structure
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment