Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Package registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Alexey Alyaev
wine
Commits
dfaef530
Commit
dfaef530
authored
10 years ago
by
Francois Gouget
Committed by
Alexandre Julliard
10 years ago
Browse files
Options
Downloads
Patches
Plain Diff
dsound: Reorder the interfaces to remove the need for forward declarations.
parent
82c298ee
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
dlls/dsound/dsound.c
+838
-837
838 additions, 837 deletions
dlls/dsound/dsound.c
dlls/dsound/dsound_private.h
+0
-14
0 additions, 14 deletions
dlls/dsound/dsound_private.h
with
838 additions
and
851 deletions
dlls/dsound/dsound.c
+
838
−
837
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
*
DirectSound
Device
*/
static
inline
I
DirectSound
Impl
*
impl_from_IUnknown
(
IUnknown
*
ifa
ce
)
static
HRESULT
DirectSound
Device_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
I
DirectSound
8Impl_GetCaps
(
IDirectSound8
*
iface
,
DSCAPS
*
dscaps
)
HRESULT
DirectSound
Device_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
"
,
de
bugstr_guid
(
lpcGUID
),
ppDS
,
pUnkOuter
);
TRACE
(
"(%p,
%p)
\n
"
,
de
vice
,
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
));
}
/*******************************************************************************
*
DirectSound
Device
*
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
"
,
de
vice
,
pDSB
);
TRACE
(
"(%
s,%
p,%p)
\n
"
,
de
bugstr_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
);
}
}
This diff is collapsed.
Click to expand it.
dlls/dsound/dsound_private.h
+
0
−
14
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
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment