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
e786998d
Commit
e786998d
authored
Sep 27, 2011
by
Andrew Eikum
Committed by
Alexandre Julliard
Sep 27, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dsound: Reimplement rendering devices on mmdevapi.
parent
4b8a2963
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
850 additions
and
357 deletions
+850
-357
Makefile.in
dlls/dsound/Makefile.in
+1
-1
dsound.c
dlls/dsound/dsound.c
+119
-100
dsound_main.c
dlls/dsound/dsound_main.c
+301
-62
dsound_private.h
dlls/dsound/dsound_private.h
+20
-5
mixer.c
dlls/dsound/mixer.c
+77
-57
primary.c
dlls/dsound/primary.c
+331
-131
dependency.c
dlls/mmdevapi/tests/dependency.c
+1
-1
No files found.
dlls/dsound/Makefile.in
View file @
e786998d
MODULE
=
dsound.dll
MODULE
=
dsound.dll
IMPORTLIB
=
dsound
IMPORTLIB
=
dsound
IMPORTS
=
dxguid uuid winmm ole32 advapi32
IMPORTS
=
dxguid uuid winmm ole32 advapi32
user32
C_SRCS
=
\
C_SRCS
=
\
buffer.c
\
buffer.c
\
...
...
dlls/dsound/dsound.c
View file @
e786998d
...
@@ -23,12 +23,12 @@
...
@@ -23,12 +23,12 @@
#include <stdarg.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdio.h>
#define COBJMACROS
#define NONAMELESSSTRUCT
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#define NONAMELESSUNION
#include "windef.h"
#include "windef.h"
#include "winbase.h"
#include "winbase.h"
#include "winuser.h"
#include "winuser.h"
#include "mmsystem.h"
#include "winternl.h"
#include "winternl.h"
#include "mmddk.h"
#include "mmddk.h"
#include "wingdi.h"
#include "wingdi.h"
...
@@ -1248,6 +1248,10 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
...
@@ -1248,6 +1248,10 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
RtlAcquireResourceShared
(
&
(
device
->
buffer_list_lock
),
TRUE
);
RtlAcquireResourceShared
(
&
(
device
->
buffer_list_lock
),
TRUE
);
RtlReleaseResource
(
&
(
device
->
buffer_list_lock
));
RtlReleaseResource
(
&
(
device
->
buffer_list_lock
));
EnterCriticalSection
(
&
DSOUND_renderers_lock
);
list_remove
(
&
device
->
entry
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
/* It is allowed to release this object even when buffers are playing */
/* It is allowed to release this object even when buffers are playing */
if
(
device
->
buffers
)
{
if
(
device
->
buffers
)
{
WARN
(
"%d secondary buffers not released
\n
"
,
device
->
nrofbuffers
);
WARN
(
"%d secondary buffers not released
\n
"
,
device
->
nrofbuffers
);
...
@@ -1264,9 +1268,14 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
...
@@ -1264,9 +1268,14 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
if
(
hr
!=
DS_OK
)
if
(
hr
!=
DS_OK
)
WARN
(
"DSOUND_PrimaryDestroy failed
\n
"
);
WARN
(
"DSOUND_PrimaryDestroy failed
\n
"
);
waveOutClose
(
device
->
hwo
);
if
(
device
->
client
)
IAudioClient_Release
(
device
->
client
);
DSOUND_renderer
[
device
->
drvdesc
.
dnDevNode
]
=
NULL
;
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
->
tmp_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
mix_buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
mix_buffer
);
...
@@ -1334,14 +1343,57 @@ HRESULT DirectSoundDevice_GetCaps(
...
@@ -1334,14 +1343,57 @@ HRESULT DirectSoundDevice_GetCaps(
return
DS_OK
;
return
DS_OK
;
}
}
static
BOOL
DSOUND_check_supported
(
IAudioClient
*
client
,
DWORD
rate
,
DWORD
depth
,
WORD
channels
)
{
WAVEFORMATEX
fmt
,
*
junk
;
HRESULT
hr
;
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
;
hr
=
IAudioClient_IsFormatSupported
(
client
,
AUDCLNT_SHAREMODE_SHARED
,
&
fmt
,
&
junk
);
if
(
SUCCEEDED
(
hr
))
CoTaskMemFree
(
junk
);
return
hr
==
S_OK
;
}
static
UINT
DSOUND_create_timer
(
LPTIMECALLBACK
cb
,
DWORD_PTR
user
)
{
UINT
triggertime
=
DS_TIME_DEL
,
res
=
DS_TIME_RES
,
id
;
TIMECAPS
time
;
timeGetDevCaps
(
&
time
,
sizeof
(
TIMECAPS
));
TRACE
(
"Minimum timer resolution: %u, max timer: %u
\n
"
,
time
.
wPeriodMin
,
time
.
wPeriodMax
);
if
(
triggertime
<
time
.
wPeriodMin
)
triggertime
=
time
.
wPeriodMin
;
if
(
res
<
time
.
wPeriodMin
)
res
=
time
.
wPeriodMin
;
if
(
timeBeginPeriod
(
res
)
==
TIMERR_NOCANDO
)
WARN
(
"Could not set minimum resolution, don't expect sound
\n
"
);
id
=
timeSetEvent
(
triggertime
,
res
,
cb
,
user
,
TIME_PERIODIC
|
TIME_KILL_SYNCHRONOUS
);
if
(
!
id
)
{
WARN
(
"Timer not created! Retrying without TIME_KILL_SYNCHRONOUS
\n
"
);
id
=
timeSetEvent
(
triggertime
,
res
,
cb
,
user
,
TIME_PERIODIC
);
if
(
!
id
)
ERR
(
"Could not create timer, sound playback will not occur
\n
"
);
}
return
id
;
}
HRESULT
DirectSoundDevice_Initialize
(
DirectSoundDevice
**
ppDevice
,
LPCGUID
lpcGUID
)
HRESULT
DirectSoundDevice_Initialize
(
DirectSoundDevice
**
ppDevice
,
LPCGUID
lpcGUID
)
{
{
HRESULT
hr
=
DS_OK
;
HRESULT
hr
=
DS_OK
;
unsigned
wod
,
wodn
;
BOOLEAN
found
=
FALSE
;
GUID
devGUID
;
GUID
devGUID
;
DirectSoundDevice
*
device
=
*
ppD
evice
;
DirectSoundDevice
*
d
evice
;
WAVEOUTCAPSA
woc
;
IMMDevice
*
mmdevice
;
TRACE
(
"(%p,%s)
\n
"
,
ppDevice
,
debugstr_guid
(
lpcGUID
));
TRACE
(
"(%p,%s)
\n
"
,
ppDevice
,
debugstr_guid
(
lpcGUID
));
...
@@ -1354,130 +1406,97 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
...
@@ -1354,130 +1406,97 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
if
(
!
lpcGUID
||
IsEqualGUID
(
lpcGUID
,
&
GUID_NULL
))
if
(
!
lpcGUID
||
IsEqualGUID
(
lpcGUID
,
&
GUID_NULL
))
lpcGUID
=
&
DSDEVID_DefaultPlayback
;
lpcGUID
=
&
DSDEVID_DefaultPlayback
;
if
(
IsEqualGUID
(
lpcGUID
,
&
DSDEVID_DefaultCapture
)
||
IsEqualGUID
(
lpcGUID
,
&
DSDEVID_DefaultVoiceCapture
))
return
DSERR_NODRIVER
;
if
(
GetDeviceID
(
lpcGUID
,
&
devGUID
)
!=
DS_OK
)
{
if
(
GetDeviceID
(
lpcGUID
,
&
devGUID
)
!=
DS_OK
)
{
WARN
(
"invalid parameter: lpcGUID
\n
"
);
WARN
(
"invalid parameter: lpcGUID
\n
"
);
return
DSERR_INVALIDPARAM
;
return
DSERR_INVALIDPARAM
;
}
}
/* Enumerate WINMM audio devices and find the one we want */
hr
=
get_mmdevice
(
eRender
,
&
devGUID
,
&
mmdevice
);
wodn
=
waveOutGetNumDevs
();
if
(
FAILED
(
hr
))
if
(
!
wodn
)
{
return
hr
;
WARN
(
"no driver
\n
"
);
return
DSERR_NODRIVER
;
}
for
(
wod
=
0
;
wod
<
wodn
;
wod
++
)
{
if
(
IsEqualGUID
(
&
devGUID
,
&
DSOUND_renderer_guids
[
wod
]))
{
found
=
TRUE
;
break
;
}
}
if
(
found
==
FALSE
)
{
EnterCriticalSection
(
&
DSOUND_renderers_lock
);
WARN
(
"No device found matching given ID!
\n
"
);
return
DSERR_NODRIVER
;
}
if
(
DSOUND_renderer
[
wod
])
{
LIST_FOR_EACH_ENTRY
(
device
,
&
DSOUND_renderers
,
DirectSoundDevice
,
entry
)
{
if
(
IsEqualGUID
(
&
devGUID
,
&
DSOUND_renderer
[
wod
]
->
guid
))
{
if
(
IsEqualGUID
(
&
device
->
guid
,
&
devGUID
))
{
device
=
DSOUND_renderer
[
wod
]
;
IMMDevice_Release
(
mmdevice
)
;
DirectSoundDevice_AddRef
(
device
);
DirectSoundDevice_AddRef
(
device
);
*
ppDevice
=
device
;
*
ppDevice
=
device
;
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
return
DS_OK
;
return
DS_OK
;
}
else
{
ERR
(
"device GUID doesn't match
\n
"
);
hr
=
DSERR_GENERIC
;
return
hr
;
}
}
}
else
{
}
hr
=
DirectSoundDevice_Create
(
&
device
);
hr
=
DirectSoundDevice_Create
(
&
device
);
if
(
hr
!=
DS_OK
)
{
if
(
FAILED
(
hr
))
{
WARN
(
"DirectSoundDevice_Create failed
\n
"
);
WARN
(
"DirectSoundDevice_Create failed
\n
"
);
IMMDevice_Release
(
mmdevice
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
return
hr
;
return
hr
;
}
}
}
*
ppDevice
=
device
;
device
->
mmdevice
=
mm
device
;
device
->
guid
=
devGUID
;
device
->
guid
=
devGUID
;
device
->
drvdesc
.
dnDevNode
=
wod
;
hr
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
hr
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
FAILED
(
hr
))
if
(
FAILED
(
hr
))
{
{
HeapFree
(
GetProcessHeap
(),
0
,
device
);
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
IMMDevice_Release
(
mmdevice
);
WARN
(
"DSOUND_ReopenDevice failed: %08x
\n
"
,
hr
);
WARN
(
"DSOUND_ReopenDevice failed: %08x
\n
"
,
hr
);
return
hr
;
return
hr
;
}
}
hr
=
mmErr
(
waveOutGetDevCapsA
(
device
->
drvdesc
.
dnDevNode
,
&
woc
,
sizeof
(
woc
)));
if
(
hr
!=
DS_OK
)
{
WARN
(
"waveOutGetDevCaps failed
\n
"
);
return
hr
;
}
ZeroMemory
(
&
device
->
drvcaps
,
sizeof
(
device
->
drvcaps
));
ZeroMemory
(
&
device
->
drvcaps
,
sizeof
(
device
->
drvcaps
));
if
((
woc
.
dwFormats
&
WAVE_FORMAT_1M08
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_2M08
)
||
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
8
,
1
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_4M08
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
8
,
1
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_48M08
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
8
,
1
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_96M08
))
{
DSOUND_check_supported
(
device
->
client
,
48000
,
8
,
1
)
||
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY8BIT
;
DSOUND_check_supported
(
device
->
client
,
96000
,
8
,
1
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARYMONO
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY8BIT
|
DSCAPS_PRIMARYMONO
;
}
if
((
woc
.
dwFormats
&
WAVE_FORMAT_1M16
)
||
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
16
,
1
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_2M16
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
16
,
1
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_4M16
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
16
,
1
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_48M16
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
16
,
1
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_96M16
))
{
DSOUND_check_supported
(
device
->
client
,
96000
,
16
,
1
))
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY16BIT
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY16BIT
|
DSCAPS_PRIMARYMONO
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARYMONO
;
}
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
8
,
2
)
||
if
((
woc
.
dwFormats
&
WAVE_FORMAT_1S08
)
||
DSOUND_check_supported
(
device
->
client
,
22050
,
8
,
2
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_2S08
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
8
,
2
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_4S08
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
8
,
2
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_48S08
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
8
,
2
))
(
woc
.
dwFormats
&
WAVE_FORMAT_96S08
))
{
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY8BIT
|
DSCAPS_PRIMARYSTEREO
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY8BIT
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARYSTEREO
;
if
(
DSOUND_check_supported
(
device
->
client
,
11025
,
16
,
2
)
||
}
DSOUND_check_supported
(
device
->
client
,
22050
,
16
,
2
)
||
if
((
woc
.
dwFormats
&
WAVE_FORMAT_1S16
)
||
DSOUND_check_supported
(
device
->
client
,
44100
,
16
,
2
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_2S16
)
||
DSOUND_check_supported
(
device
->
client
,
48000
,
16
,
2
)
||
(
woc
.
dwFormats
&
WAVE_FORMAT_4S16
)
||
DSOUND_check_supported
(
device
->
client
,
96000
,
16
,
2
))
(
woc
.
dwFormats
&
WAVE_FORMAT_48S16
)
||
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY16BIT
|
DSCAPS_PRIMARYSTEREO
;
(
woc
.
dwFormats
&
WAVE_FORMAT_96S16
))
{
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARY16BIT
;
device
->
drvcaps
.
dwFlags
|=
DSCAPS_PRIMARYSTEREO
;
}
if
(
ds_emuldriver
)
device
->
drvcaps
.
dwFlags
|=
DSCAPS_EMULDRIVER
;
device
->
drvcaps
.
dwMinSecondarySampleRate
=
DSBFREQUENCY_MIN
;
device
->
drvcaps
.
dwMinSecondarySampleRate
=
DSBFREQUENCY_MIN
;
device
->
drvcaps
.
dwMaxSecondarySampleRate
=
DSBFREQUENCY_MAX
;
device
->
drvcaps
.
dwMaxSecondarySampleRate
=
DSBFREQUENCY_MAX
;
ZeroMemory
(
&
device
->
volpan
,
sizeof
(
device
->
volpan
));
ZeroMemory
(
&
device
->
volpan
,
sizeof
(
device
->
volpan
));
hr
=
DSOUND_PrimaryCreate
(
device
);
hr
=
DSOUND_PrimaryCreate
(
device
);
if
(
hr
==
DS_OK
)
{
if
(
hr
==
DS_OK
)
UINT
triggertime
=
DS_TIME_DEL
,
res
=
DS_TIME_RES
,
id
;
device
->
timerID
=
DSOUND_create_timer
(
DSOUND_timer
,
(
DWORD_PTR
)
device
);
TIMECAPS
time
;
else
WARN
(
"DSOUND_PrimaryCreate failed: %08x
\n
"
,
hr
);
DSOUND_renderer
[
device
->
drvdesc
.
dnDevNode
]
=
device
;
*
ppDevice
=
device
;
timeGetDevCaps
(
&
time
,
sizeof
(
TIMECAPS
));
list_add_tail
(
&
DSOUND_renderers
,
&
device
->
entry
);
TRACE
(
"Minimum timer resolution: %u, max timer: %u
\n
"
,
time
.
wPeriodMin
,
time
.
wPeriodMax
);
if
(
triggertime
<
time
.
wPeriodMin
)
LeaveCriticalSection
(
&
DSOUND_renderers_lock
);
triggertime
=
time
.
wPeriodMin
;
if
(
res
<
time
.
wPeriodMin
)
res
=
time
.
wPeriodMin
;
if
(
timeBeginPeriod
(
res
)
==
TIMERR_NOCANDO
)
WARN
(
"Could not set minimum resolution, don't expect sound
\n
"
);
id
=
timeSetEvent
(
triggertime
,
res
,
DSOUND_timer
,
(
DWORD_PTR
)
device
,
TIME_PERIODIC
|
TIME_KILL_SYNCHRONOUS
);
if
(
!
id
)
{
WARN
(
"Timer not created! Retrying without TIME_KILL_SYNCHRONOUS
\n
"
);
id
=
timeSetEvent
(
triggertime
,
res
,
DSOUND_timer
,
(
DWORD_PTR
)
device
,
TIME_PERIODIC
);
if
(
!
id
)
ERR
(
"Could not create timer, sound playback will not occur
\n
"
);
}
DSOUND_renderer
[
device
->
drvdesc
.
dnDevNode
]
->
timerID
=
id
;
}
else
{
WARN
(
"DSOUND_PrimaryCreate failed
\n
"
);
}
return
hr
;
return
hr
;
}
}
...
...
dlls/dsound/dsound_main.c
View file @
e786998d
...
@@ -50,17 +50,31 @@
...
@@ -50,17 +50,31 @@
#include "dsconf.h"
#include "dsconf.h"
#include "ks.h"
#include "ks.h"
#include "rpcproxy.h"
#include "rpcproxy.h"
#include "rpc.h"
#include "rpcndr.h"
#include "unknwn.h"
#include "oleidl.h"
#include "shobjidl.h"
#include "initguid.h"
#include "initguid.h"
#include "ksmedia.h"
#include "ksmedia.h"
#include "propkey.h"
#include "devpkey.h"
#include "dsound_private.h"
#include "dsound_private.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dsound
);
WINE_DEFAULT_DEBUG_CHANNEL
(
dsound
);
DirectSoundDevice
*
DSOUND_renderer
[
MAXWAVEDRIVERS
];
struct
list
DSOUND_renderers
=
LIST_INIT
(
DSOUND_renderers
);
CRITICAL_SECTION
DSOUND_renderers_lock
;
GUID
DSOUND_renderer_guids
[
MAXWAVEDRIVERS
];
GUID
DSOUND_renderer_guids
[
MAXWAVEDRIVERS
];
GUID
DSOUND_capture_guids
[
MAXWAVEDRIVERS
];
GUID
DSOUND_capture_guids
[
MAXWAVEDRIVERS
];
static
IMMDeviceEnumerator
*
g_devenum
;
static
CRITICAL_SECTION
g_devenum_lock
;
static
HANDLE
g_devenum_thread
;
HRESULT
mmErr
(
UINT
err
)
HRESULT
mmErr
(
UINT
err
)
{
{
switch
(
err
)
{
switch
(
err
)
{
...
@@ -196,6 +210,117 @@ static const char * get_device_id(LPCGUID pGuid)
...
@@ -196,6 +210,117 @@ static const char * get_device_id(LPCGUID pGuid)
return
debugstr_guid
(
pGuid
);
return
debugstr_guid
(
pGuid
);
}
}
/* The MMDeviceEnumerator object has to be created & destroyed
* from the same thread. */
static
DWORD
WINAPI
devenum_thread_proc
(
void
*
arg
)
{
HANDLE
evt
=
arg
;
HRESULT
hr
;
MSG
msg
;
hr
=
CoInitializeEx
(
NULL
,
COINIT_APARTMENTTHREADED
);
if
(
FAILED
(
hr
)){
ERR
(
"CoInitializeEx failed: %08x
\n
"
,
hr
);
return
1
;
}
hr
=
CoCreateInstance
(
&
CLSID_MMDeviceEnumerator
,
NULL
,
CLSCTX_INPROC_SERVER
,
&
IID_IMMDeviceEnumerator
,
(
void
**
)
&
g_devenum
);
if
(
FAILED
(
hr
)){
ERR
(
"CoCreateInstance failed: %08x
\n
"
,
hr
);
CoUninitialize
();
return
1
;
}
SetEvent
(
evt
);
PeekMessageW
(
&
msg
,
NULL
,
WM_USER
,
WM_USER
,
PM_NOREMOVE
);
while
(
GetMessageW
(
&
msg
,
NULL
,
0
,
0
)){
if
(
msg
.
hwnd
)
DispatchMessageW
(
&
msg
);
else
ERR
(
"Unknown message: %04x
\n
"
,
msg
.
message
);
}
IMMDeviceEnumerator_Release
(
g_devenum
);
g_devenum
=
NULL
;
CoUninitialize
();
return
0
;
}
static
IMMDeviceEnumerator
*
get_mmdevenum
(
void
)
{
HANDLE
events
[
2
];
DWORD
wait
;
EnterCriticalSection
(
&
g_devenum_lock
);
if
(
g_devenum
){
LeaveCriticalSection
(
&
g_devenum_lock
);
return
g_devenum
;
}
events
[
0
]
=
CreateEventW
(
NULL
,
FALSE
,
FALSE
,
NULL
);
g_devenum_thread
=
CreateThread
(
NULL
,
0
,
devenum_thread_proc
,
events
[
0
],
0
,
NULL
);
if
(
!
g_devenum_thread
){
LeaveCriticalSection
(
&
g_devenum_lock
);
CloseHandle
(
events
[
0
]);
return
NULL
;
}
events
[
1
]
=
g_devenum_thread
;
wait
=
WaitForMultipleObjects
(
2
,
events
,
FALSE
,
INFINITE
);
CloseHandle
(
events
[
0
]);
if
(
wait
!=
WAIT_OBJECT_0
){
if
(
wait
==
1
+
WAIT_OBJECT_0
){
CloseHandle
(
g_devenum_thread
);
g_devenum_thread
=
NULL
;
}
LeaveCriticalSection
(
&
g_devenum_lock
);
return
NULL
;
}
LeaveCriticalSection
(
&
g_devenum_lock
);
return
g_devenum
;
}
static
HRESULT
get_mmdevice_guid
(
IMMDevice
*
device
,
IPropertyStore
*
ps
,
GUID
*
guid
)
{
PROPVARIANT
pv
;
HRESULT
hr
;
if
(
!
ps
){
hr
=
IMMDevice_OpenPropertyStore
(
device
,
STGM_READ
,
&
ps
);
if
(
FAILED
(
hr
)){
WARN
(
"OpenPropertyStore failed: %08x
\n
"
,
hr
);
return
hr
;
}
}
else
IPropertyStore_AddRef
(
ps
);
PropVariantInit
(
&
pv
);
hr
=
IPropertyStore_GetValue
(
ps
,
&
PKEY_AudioEndpoint_GUID
,
&
pv
);
if
(
FAILED
(
hr
)){
IPropertyStore_Release
(
ps
);
WARN
(
"GetValue(GUID) failed: %08x
\n
"
,
hr
);
return
hr
;
}
CLSIDFromString
(
pv
.
u
.
pwszVal
,
guid
);
PropVariantClear
(
&
pv
);
IPropertyStore_Release
(
ps
);
return
S_OK
;
}
/***************************************************************************
/***************************************************************************
* GetDeviceID [DSOUND.9]
* GetDeviceID [DSOUND.9]
*
*
...
@@ -218,34 +343,51 @@ static const char * get_device_id(LPCGUID pGuid)
...
@@ -218,34 +343,51 @@ static const char * get_device_id(LPCGUID pGuid)
*/
*/
HRESULT
WINAPI
GetDeviceID
(
LPCGUID
pGuidSrc
,
LPGUID
pGuidDest
)
HRESULT
WINAPI
GetDeviceID
(
LPCGUID
pGuidSrc
,
LPGUID
pGuidDest
)
{
{
IMMDeviceEnumerator
*
devenum
;
EDataFlow
flow
=
(
EDataFlow
)
-
1
;
ERole
role
=
(
ERole
)
-
1
;
HRESULT
hr
;
TRACE
(
"(%s,%p)
\n
"
,
get_device_id
(
pGuidSrc
),
pGuidDest
);
TRACE
(
"(%s,%p)
\n
"
,
get_device_id
(
pGuidSrc
),
pGuidDest
);
if
(
pGuidSrc
==
NULL
)
{
if
(
!
pGuidSrc
||
!
pGuidDest
)
WARN
(
"invalid parameter: pGuidSrc == NULL
\n
"
);
return
DSERR_INVALIDPARAM
;
return
DSERR_INVALIDPARAM
;
}
if
(
pGuidDest
==
NULL
)
{
devenum
=
get_mmdevenum
();
WARN
(
"invalid parameter: pGuidDest == NULL
\n
"
);
if
(
!
devenum
)
return
DSERR_INVALIDPARAM
;
return
DSERR_GENERIC
;
}
if
(
IsEqualGUID
(
&
DSDEVID_DefaultPlayback
,
pGuidSrc
)
||
if
(
IsEqualGUID
(
&
DSDEVID_DefaultPlayback
,
pGuidSrc
)){
IsEqualGUID
(
&
DSDEVID_DefaultVoicePlayback
,
pGuidSrc
)
)
{
role
=
eMultimedia
;
*
pGuidDest
=
DSOUND_renderer_guids
[
ds_default_playback
];
flow
=
eRender
;
TRACE
(
"returns %s
\n
"
,
get_device_id
(
pGuidDest
));
}
else
if
(
IsEqualGUID
(
&
DSDEVID_DefaultVoicePlayback
,
pGuidSrc
)){
return
DS_OK
;
role
=
eCommunications
;
flow
=
eRender
;
}
else
if
(
IsEqualGUID
(
&
DSDEVID_DefaultCapture
,
pGuidSrc
)){
role
=
eMultimedia
;
flow
=
eCapture
;
}
else
if
(
IsEqualGUID
(
&
DSDEVID_DefaultVoiceCapture
,
pGuidSrc
)){
role
=
eCommunications
;
flow
=
eCapture
;
}
if
(
role
!=
(
ERole
)
-
1
&&
flow
!=
(
EDataFlow
)
-
1
){
IMMDevice
*
device
;
hr
=
IMMDeviceEnumerator_GetDefaultAudioEndpoint
(
devenum
,
flow
,
role
,
&
device
);
if
(
FAILED
(
hr
)){
WARN
(
"GetDefaultAudioEndpoint failed: %08x
\n
"
,
hr
);
return
DSERR_NODRIVER
;
}
}
if
(
IsEqualGUID
(
&
DSDEVID_DefaultCapture
,
pGuidSrc
)
||
hr
=
get_mmdevice_guid
(
device
,
NULL
,
pGuidDest
);
IsEqualGUID
(
&
DSDEVID_DefaultVoiceCapture
,
pGuidSrc
)
)
{
IMMDevice_Release
(
device
);
*
pGuidDest
=
DSOUND_capture_guids
[
ds_default_capture
];
TRACE
(
"returns %s
\n
"
,
get_device_id
(
pGuidDest
));
return
(
hr
==
S_OK
)
?
DS_OK
:
hr
;
return
DS_OK
;
}
}
*
pGuidDest
=
*
pGuidSrc
;
*
pGuidDest
=
*
pGuidSrc
;
TRACE
(
"returns %s
\n
"
,
get_device_id
(
pGuidDest
));
return
DS_OK
;
return
DS_OK
;
}
}
...
@@ -297,6 +439,141 @@ HRESULT WINAPI DirectSoundEnumerateA(
...
@@ -297,6 +439,141 @@ HRESULT WINAPI DirectSoundEnumerateA(
return
DirectSoundEnumerateW
(
a_to_w_callback
,
&
context
);
return
DirectSoundEnumerateW
(
a_to_w_callback
,
&
context
);
}
}
HRESULT
get_mmdevice
(
EDataFlow
flow
,
const
GUID
*
tgt
,
IMMDevice
**
device
)
{
IMMDeviceEnumerator
*
devenum
;
IMMDeviceCollection
*
coll
;
UINT
count
,
i
;
HRESULT
hr
;
devenum
=
get_mmdevenum
();
if
(
!
devenum
)
return
DSERR_GENERIC
;
hr
=
IMMDeviceEnumerator_EnumAudioEndpoints
(
devenum
,
flow
,
DEVICE_STATE_ACTIVE
,
&
coll
);
if
(
FAILED
(
hr
)){
WARN
(
"EnumAudioEndpoints failed: %08x
\n
"
,
hr
);
return
hr
;
}
hr
=
IMMDeviceCollection_GetCount
(
coll
,
&
count
);
if
(
FAILED
(
hr
)){
IMMDeviceCollection_Release
(
coll
);
WARN
(
"GetCount failed: %08x
\n
"
,
hr
);
return
hr
;
}
for
(
i
=
0
;
i
<
count
;
++
i
){
GUID
guid
;
hr
=
IMMDeviceCollection_Item
(
coll
,
i
,
device
);
if
(
FAILED
(
hr
))
continue
;
hr
=
get_mmdevice_guid
(
*
device
,
NULL
,
&
guid
);
if
(
FAILED
(
hr
)){
IMMDevice_Release
(
*
device
);
continue
;
}
if
(
IsEqualGUID
(
&
guid
,
tgt
))
return
DS_OK
;
IMMDevice_Release
(
*
device
);
}
WARN
(
"No device with GUID %s found!
\n
"
,
wine_dbgstr_guid
(
tgt
));
return
DSERR_INVALIDPARAM
;
}
static
HRESULT
enumerate_mmdevices
(
EDataFlow
flow
,
GUID
*
guids
,
LPDSENUMCALLBACKW
cb
,
void
*
user
)
{
IMMDeviceEnumerator
*
devenum
;
IMMDeviceCollection
*
coll
;
UINT
count
,
i
;
BOOL
keep_going
;
HRESULT
hr
;
static
const
WCHAR
primary_desc
[]
=
{
'P'
,
'r'
,
'i'
,
'm'
,
'a'
,
'r'
,
'y'
,
' '
,
'S'
,
'o'
,
'u'
,
'n'
,
'd'
,
' '
,
'D'
,
'r'
,
'i'
,
'v'
,
'e'
,
'r'
,
0
};
static
const
WCHAR
empty_drv
[]
=
{
0
};
static
const
WCHAR
wine_vxd_drv
[]
=
{
'w'
,
'i'
,
'n'
,
'e'
,
'm'
,
'm'
,
'.'
,
'v'
,
'x'
,
'd'
,
0
};
devenum
=
get_mmdevenum
();
if
(
!
devenum
)
return
DS_OK
;
hr
=
IMMDeviceEnumerator_EnumAudioEndpoints
(
g_devenum
,
flow
,
DEVICE_STATE_ACTIVE
,
&
coll
);
if
(
FAILED
(
hr
)){
WARN
(
"EnumAudioEndpoints failed: %08x
\n
"
,
hr
);
return
DS_OK
;
}
hr
=
IMMDeviceCollection_GetCount
(
coll
,
&
count
);
if
(
FAILED
(
hr
)){
IMMDeviceCollection_Release
(
coll
);
WARN
(
"GetCount failed: %08x
\n
"
,
hr
);
return
DS_OK
;
}
if
(
count
==
0
)
return
DS_OK
;
keep_going
=
cb
(
NULL
,
primary_desc
,
empty_drv
,
user
);
for
(
i
=
0
;
keep_going
&&
i
<
count
;
++
i
){
IMMDevice
*
device
;
IPropertyStore
*
ps
;
PROPVARIANT
pv
;
PropVariantInit
(
&
pv
);
hr
=
IMMDeviceCollection_Item
(
coll
,
i
,
&
device
);
if
(
FAILED
(
hr
)){
WARN
(
"Item failed: %08x
\n
"
,
hr
);
continue
;
}
hr
=
IMMDevice_OpenPropertyStore
(
device
,
STGM_READ
,
&
ps
);
if
(
FAILED
(
hr
)){
IMMDevice_Release
(
device
);
WARN
(
"OpenPropertyStore failed: %08x
\n
"
,
hr
);
continue
;
}
hr
=
get_mmdevice_guid
(
device
,
ps
,
&
guids
[
i
]);
if
(
FAILED
(
hr
)){
IPropertyStore_Release
(
ps
);
IMMDevice_Release
(
device
);
continue
;
}
hr
=
IPropertyStore_GetValue
(
ps
,
(
const
PROPERTYKEY
*
)
&
DEVPKEY_Device_FriendlyName
,
&
pv
);
if
(
FAILED
(
hr
)){
IPropertyStore_Release
(
ps
);
IMMDevice_Release
(
device
);
WARN
(
"GetValue(FriendlyName) failed: %08x
\n
"
,
hr
);
continue
;
}
keep_going
=
cb
(
&
guids
[
i
],
pv
.
u
.
pwszVal
,
wine_vxd_drv
,
user
);
PropVariantClear
(
&
pv
);
IPropertyStore_Release
(
ps
);
IMMDevice_Release
(
device
);
}
IMMDeviceCollection_Release
(
coll
);
return
DS_OK
;
}
/***************************************************************************
/***************************************************************************
* DirectSoundEnumerateW [DSOUND.3]
* DirectSoundEnumerateW [DSOUND.3]
*
*
...
@@ -314,17 +591,7 @@ HRESULT WINAPI DirectSoundEnumerateW(
...
@@ -314,17 +591,7 @@ HRESULT WINAPI DirectSoundEnumerateW(
LPDSENUMCALLBACKW
lpDSEnumCallback
,
LPDSENUMCALLBACKW
lpDSEnumCallback
,
LPVOID
lpContext
)
LPVOID
lpContext
)
{
{
unsigned
devs
,
wod
;
TRACE
(
"(%p,%p)
\n
"
,
lpDSEnumCallback
,
lpContext
);
GUID
guid
;
int
err
;
WAVEOUTCAPSW
caps
;
const
static
WCHAR
winmmW
[]
=
{
'w'
,
'i'
,
'n'
,
'm'
,
'm'
,
'.'
,
'd'
,
'l'
,
'l'
,
0
};
const
static
WCHAR
primary_driverW
[]
=
{
'P'
,
'r'
,
'i'
,
'm'
,
'a'
,
'r'
,
'y'
,
' '
,
'S'
,
'o'
,
'u'
,
'n'
,
'd'
,
' '
,
'D'
,
'r'
,
'i'
,
'v'
,
'e'
,
'r'
,
0
};
TRACE
(
"lpDSEnumCallback = %p, lpContext = %p
\n
"
,
lpDSEnumCallback
,
lpContext
);
if
(
lpDSEnumCallback
==
NULL
)
{
if
(
lpDSEnumCallback
==
NULL
)
{
WARN
(
"invalid parameter: lpDSEnumCallback == NULL
\n
"
);
WARN
(
"invalid parameter: lpDSEnumCallback == NULL
\n
"
);
...
@@ -333,36 +600,8 @@ HRESULT WINAPI DirectSoundEnumerateW(
...
@@ -333,36 +600,8 @@ HRESULT WINAPI DirectSoundEnumerateW(
setup_dsound_options
();
setup_dsound_options
();
devs
=
waveOutGetNumDevs
();
return
enumerate_mmdevices
(
eRender
,
DSOUND_renderer_guids
,
if
(
devs
>
0
)
{
lpDSEnumCallback
,
lpContext
);
if
(
GetDeviceID
(
&
DSDEVID_DefaultPlayback
,
&
guid
)
==
DS_OK
)
{
static
const
WCHAR
empty
[]
=
{
0
};
for
(
wod
=
0
;
wod
<
devs
;
++
wod
)
{
if
(
IsEqualGUID
(
&
guid
,
&
DSOUND_renderer_guids
[
wod
]
)
)
{
err
=
mmErr
(
waveOutGetDevCapsW
(
wod
,
&
caps
,
sizeof
(
caps
)));
if
(
err
==
DS_OK
)
{
TRACE
(
"calling lpDSEnumCallback(NULL,
\"
%s
\"
,
\"
%s
\"
,%p)
\n
"
,
"Primary Sound Driver"
,
""
,
lpContext
);
if
(
lpDSEnumCallback
(
NULL
,
primary_driverW
,
empty
,
lpContext
)
==
FALSE
)
return
DS_OK
;
}
}
}
}
}
for
(
wod
=
0
;
wod
<
devs
;
++
wod
)
{
err
=
mmErr
(
waveOutGetDevCapsW
(
wod
,
&
caps
,
sizeof
(
caps
)));
if
(
err
==
DS_OK
)
{
TRACE
(
"calling lpDSEnumCallback(%s,
\"
%s
\"
,
\"
%s
\"
,%p)
\n
"
,
debugstr_guid
(
&
DSOUND_renderer_guids
[
wod
]),
wine_dbgstr_w
(
caps
.
szPname
),
"winmm.dll"
,
lpContext
);
if
(
lpDSEnumCallback
(
&
DSOUND_renderer_guids
[
wod
],
caps
.
szPname
,
winmmW
,
lpContext
)
==
FALSE
)
return
DS_OK
;
}
}
return
DS_OK
;
}
}
/***************************************************************************
/***************************************************************************
...
@@ -645,15 +884,15 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
...
@@ -645,15 +884,15 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
case
DLL_PROCESS_ATTACH
:
case
DLL_PROCESS_ATTACH
:
TRACE
(
"DLL_PROCESS_ATTACH
\n
"
);
TRACE
(
"DLL_PROCESS_ATTACH
\n
"
);
for
(
i
=
0
;
i
<
MAXWAVEDRIVERS
;
i
++
)
{
for
(
i
=
0
;
i
<
MAXWAVEDRIVERS
;
i
++
)
{
DSOUND_renderer
[
i
]
=
NULL
;
DSOUND_capture
[
i
]
=
NULL
;
DSOUND_capture
[
i
]
=
NULL
;
INIT_GUID
(
DSOUND_renderer_guids
[
i
],
0xbd6dd71a
,
0x3deb
,
0x11d1
,
0xb1
,
0x71
,
0x00
,
0xc0
,
0x4f
,
0xc2
,
0x00
,
0x00
+
i
);
INIT_GUID
(
DSOUND_capture_guids
[
i
],
0xbd6dd71b
,
0x3deb
,
0x11d1
,
0xb1
,
0x71
,
0x00
,
0xc0
,
0x4f
,
0xc2
,
0x00
,
0x00
+
i
);
INIT_GUID
(
DSOUND_capture_guids
[
i
],
0xbd6dd71b
,
0x3deb
,
0x11d1
,
0xb1
,
0x71
,
0x00
,
0xc0
,
0x4f
,
0xc2
,
0x00
,
0x00
+
i
);
}
}
instance
=
hInstDLL
;
instance
=
hInstDLL
;
DisableThreadLibraryCalls
(
hInstDLL
);
DisableThreadLibraryCalls
(
hInstDLL
);
/* Increase refcount on dsound by 1 */
/* Increase refcount on dsound by 1 */
GetModuleHandleExW
(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
(
LPCWSTR
)
hInstDLL
,
&
hInstDLL
);
GetModuleHandleExW
(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
(
LPCWSTR
)
hInstDLL
,
&
hInstDLL
);
InitializeCriticalSection
(
&
DSOUND_renderers_lock
);
InitializeCriticalSection
(
&
g_devenum_lock
);
break
;
break
;
case
DLL_PROCESS_DETACH
:
case
DLL_PROCESS_DETACH
:
TRACE
(
"DLL_PROCESS_DETACH
\n
"
);
TRACE
(
"DLL_PROCESS_DETACH
\n
"
);
...
...
dlls/dsound/dsound_private.h
View file @
e786998d
...
@@ -23,6 +23,11 @@
...
@@ -23,6 +23,11 @@
#define DS_TIME_RES 2
/* Resolution of multimedia timer */
#define DS_TIME_RES 2
/* Resolution of multimedia timer */
#define DS_TIME_DEL 10
/* Delay of multimedia timer callback, and duration of HEL fragment */
#define DS_TIME_DEL 10
/* Delay of multimedia timer callback, and duration of HEL fragment */
#include "wingdi.h"
#include "mmdeviceapi.h"
#include "audioclient.h"
#include "mmsystem.h"
#include "wine/list.h"
#include "wine/list.h"
extern
int
ds_emuldriver
DECLSPEC_HIDDEN
;
extern
int
ds_emuldriver
DECLSPEC_HIDDEN
;
...
@@ -132,9 +137,8 @@ struct DirectSoundDevice
...
@@ -132,9 +137,8 @@ struct DirectSoundDevice
DSDRIVERCAPS
drvcaps
;
DSDRIVERCAPS
drvcaps
;
DWORD
priolevel
;
DWORD
priolevel
;
PWAVEFORMATEX
pwfx
;
PWAVEFORMATEX
pwfx
;
HWAVEOUT
hwo
;
LPWAVEHDR
pwave
;
UINT
timerID
,
pwplay
,
pwqueue
,
prebuf
,
helfrags
;
UINT
timerID
,
pwplay
,
pwqueue
,
prebuf
,
helfrags
;
UINT64
last_pos_bytes
;
DWORD
fraglen
;
DWORD
fraglen
;
LPBYTE
buffer
;
LPBYTE
buffer
;
DWORD
writelead
,
buflen
,
state
,
playpos
,
mixpos
;
DWORD
writelead
,
buflen
,
state
,
playpos
,
mixpos
;
...
@@ -156,6 +160,14 @@ struct DirectSoundDevice
...
@@ -156,6 +160,14 @@ struct DirectSoundDevice
IDirectSound3DListenerImpl
*
listener
;
IDirectSound3DListenerImpl
*
listener
;
DS3DLISTENER
ds3dl
;
DS3DLISTENER
ds3dl
;
BOOL
ds3dl_need_recalc
;
BOOL
ds3dl_need_recalc
;
IMMDevice
*
mmdevice
;
IAudioClient
*
client
;
IAudioClock
*
clock
;
IAudioStreamVolume
*
volume
;
IAudioRenderClient
*
render
;
struct
list
entry
;
};
};
/* reference counted buffer memory for duplicated buffer memory */
/* reference counted buffer memory for duplicated buffer memory */
...
@@ -397,7 +409,6 @@ void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DW
...
@@ -397,7 +409,6 @@ void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DW
DWORD
DSOUND_secpos_to_bufpos
(
const
IDirectSoundBufferImpl
*
dsb
,
DWORD
secpos
,
DWORD
secmixpos
,
DWORD
*
overshot
)
DECLSPEC_HIDDEN
;
DWORD
DSOUND_secpos_to_bufpos
(
const
IDirectSoundBufferImpl
*
dsb
,
DWORD
secpos
,
DWORD
secmixpos
,
DWORD
*
overshot
)
DECLSPEC_HIDDEN
;
void
CALLBACK
DSOUND_timer
(
UINT
timerID
,
UINT
msg
,
DWORD_PTR
dwUser
,
DWORD_PTR
dw1
,
DWORD_PTR
dw2
)
DECLSPEC_HIDDEN
;
void
CALLBACK
DSOUND_timer
(
UINT
timerID
,
UINT
msg
,
DWORD_PTR
dwUser
,
DWORD_PTR
dw1
,
DWORD_PTR
dw2
)
DECLSPEC_HIDDEN
;
void
CALLBACK
DSOUND_callback
(
HWAVEOUT
hwo
,
UINT
msg
,
DWORD_PTR
dwUser
,
DWORD_PTR
dw1
,
DWORD_PTR
dw2
)
DECLSPEC_HIDDEN
;
/* sound3d.c */
/* sound3d.c */
...
@@ -416,12 +427,16 @@ HRESULT DSOUND_CaptureCreate8(REFIID riid, LPDIRECTSOUNDCAPTURE8 *ppDSC8) DECLSP
...
@@ -416,12 +427,16 @@ HRESULT DSOUND_CaptureCreate8(REFIID riid, LPDIRECTSOUNDCAPTURE8 *ppDSC8) DECLSP
#define DSOUND_FREQSHIFT (20)
#define DSOUND_FREQSHIFT (20)
extern
DirectSoundDevice
*
DSOUND_renderer
[
MAXWAVEDRIVERS
]
DECLSPEC_HIDDEN
;
extern
CRITICAL_SECTION
DSOUND_renderers_lock
DECLSPEC_HIDDEN
;
extern
GUID
DSOUND_renderer_guids
[
MAXWAVEDRIVERS
]
DECLSPEC_HIDDEN
;
extern
struct
list
DSOUND_renderers
DECLSPEC_HIDDEN
;
extern
DirectSoundCaptureDevice
*
DSOUND_capture
[
MAXWAVEDRIVERS
]
DECLSPEC_HIDDEN
;
extern
DirectSoundCaptureDevice
*
DSOUND_capture
[
MAXWAVEDRIVERS
]
DECLSPEC_HIDDEN
;
extern
GUID
DSOUND_renderer_guids
[
MAXWAVEDRIVERS
]
DECLSPEC_HIDDEN
;
extern
GUID
DSOUND_capture_guids
[
MAXWAVEDRIVERS
]
DECLSPEC_HIDDEN
;
extern
GUID
DSOUND_capture_guids
[
MAXWAVEDRIVERS
]
DECLSPEC_HIDDEN
;
HRESULT
mmErr
(
UINT
err
)
DECLSPEC_HIDDEN
;
HRESULT
mmErr
(
UINT
err
)
DECLSPEC_HIDDEN
;
void
setup_dsound_options
(
void
)
DECLSPEC_HIDDEN
;
void
setup_dsound_options
(
void
)
DECLSPEC_HIDDEN
;
const
char
*
dumpCooperativeLevel
(
DWORD
level
)
DECLSPEC_HIDDEN
;
const
char
*
dumpCooperativeLevel
(
DWORD
level
)
DECLSPEC_HIDDEN
;
HRESULT
get_mmdevice
(
EDataFlow
flow
,
const
GUID
*
tgt
,
IMMDevice
**
device
)
DECLSPEC_HIDDEN
;
dlls/dsound/mixer.c
View file @
e786998d
...
@@ -26,6 +26,7 @@
...
@@ -26,6 +26,7 @@
#include <stdarg.h>
#include <stdarg.h>
#include <math.h>
/* Insomnia - pow() function */
#include <math.h>
/* Insomnia - pow() function */
#define COBJMACROS
#define NONAMELESSSTRUCT
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#define NONAMELESSUNION
#include "windef.h"
#include "windef.h"
...
@@ -742,17 +743,21 @@ static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos
...
@@ -742,17 +743,21 @@ static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos
static
void
DSOUND_WaveQueue
(
DirectSoundDevice
*
device
,
BOOL
force
)
static
void
DSOUND_WaveQueue
(
DirectSoundDevice
*
device
,
BOOL
force
)
{
{
DWORD
prebuf_frags
,
wave_writepos
,
wave_fragpos
,
i
;
DWORD
prebuf_frames
,
buf_offs_bytes
,
wave_fragpos
;
int
prebuf_frags
;
BYTE
*
buffer
;
HRESULT
hr
;
TRACE
(
"(%p)
\n
"
,
device
);
TRACE
(
"(%p)
\n
"
,
device
);
/* calculate the current wave frag position */
/* calculate the current wave frag position */
wave_fragpos
=
(
device
->
pwplay
+
device
->
pwqueue
)
%
device
->
helfrags
;
wave_fragpos
=
(
device
->
pwplay
+
device
->
pwqueue
)
%
device
->
helfrags
;
/* calculate the current wave write position */
/* calculate the current wave write position */
wave_writepo
s
=
wave_fragpos
*
device
->
fraglen
;
buf_offs_byte
s
=
wave_fragpos
*
device
->
fraglen
;
TRACE
(
"wave_fragpos = %i,
wave_writepo
s = %i, pwqueue = %i, prebuf = %i
\n
"
,
TRACE
(
"wave_fragpos = %i,
buf_offs_byte
s = %i, pwqueue = %i, prebuf = %i
\n
"
,
wave_fragpos
,
wave_writepo
s
,
device
->
pwqueue
,
device
->
prebuf
);
wave_fragpos
,
buf_offs_byte
s
,
device
->
pwqueue
,
device
->
prebuf
);
if
(
!
force
)
if
(
!
force
)
{
{
...
@@ -776,23 +781,50 @@ static void DSOUND_WaveQueue(DirectSoundDevice *device, BOOL force)
...
@@ -776,23 +781,50 @@ static void DSOUND_WaveQueue(DirectSoundDevice *device, BOOL force)
TRACE
(
"prebuf_frags = %i
\n
"
,
prebuf_frags
);
TRACE
(
"prebuf_frags = %i
\n
"
,
prebuf_frags
);
if
(
!
prebuf_frags
)
return
;
/* adjust queue */
/* adjust queue */
device
->
pwqueue
+=
prebuf_frags
;
device
->
pwqueue
+=
prebuf_frags
;
/* get out of CS when calling the wave system */
prebuf_frames
=
((
prebuf_frags
+
wave_fragpos
>
device
->
helfrags
)
?
LeaveCriticalSection
(
&
(
device
->
mixlock
));
(
prebuf_frags
+
wave_fragpos
-
device
->
helfrags
)
:
/* **** */
(
prebuf_frags
))
*
device
->
fraglen
/
device
->
pwfx
->
nBlockAlign
;
/* queue up the new buffers */
hr
=
IAudioRenderClient_GetBuffer
(
device
->
render
,
prebuf_frames
,
&
buffer
);
for
(
i
=
0
;
i
<
prebuf_frags
;
i
++
){
if
(
FAILED
(
hr
)){
TRACE
(
"queueing wave buffer %i
\n
"
,
wave_fragpos
);
WARN
(
"GetBuffer failed: %08x
\n
"
,
hr
);
waveOutWrite
(
device
->
hwo
,
&
device
->
pwave
[
wave_fragpos
],
sizeof
(
WAVEHDR
));
return
;
wave_fragpos
++
;
wave_fragpos
%=
device
->
helfrags
;
}
}
/* **** */
memcpy
(
buffer
,
device
->
buffer
+
buf_offs_bytes
,
EnterCriticalSection
(
&
(
device
->
mixlock
));
prebuf_frames
*
device
->
pwfx
->
nBlockAlign
);
hr
=
IAudioRenderClient_ReleaseBuffer
(
device
->
render
,
prebuf_frames
,
0
);
if
(
FAILED
(
hr
)){
WARN
(
"ReleaseBuffer failed: %08x
\n
"
,
hr
);
return
;
}
/* check if anything wrapped */
prebuf_frags
=
prebuf_frags
+
wave_fragpos
-
device
->
helfrags
;
if
(
prebuf_frags
>
0
){
prebuf_frames
=
prebuf_frags
*
device
->
fraglen
/
device
->
pwfx
->
nBlockAlign
;
hr
=
IAudioRenderClient_GetBuffer
(
device
->
render
,
prebuf_frames
,
&
buffer
);
if
(
FAILED
(
hr
)){
WARN
(
"GetBuffer failed: %08x
\n
"
,
hr
);
return
;
}
memcpy
(
buffer
,
device
->
buffer
,
prebuf_frames
*
device
->
pwfx
->
nBlockAlign
);
hr
=
IAudioRenderClient_ReleaseBuffer
(
device
->
render
,
prebuf_frames
,
0
);
if
(
FAILED
(
hr
)){
WARN
(
"ReleaseBuffer failed: %08x
\n
"
,
hr
);
return
;
}
}
TRACE
(
"queue now = %i
\n
"
,
device
->
pwqueue
);
TRACE
(
"queue now = %i
\n
"
,
device
->
pwqueue
);
}
}
...
@@ -804,10 +836,39 @@ static void DSOUND_WaveQueue(DirectSoundDevice *device, BOOL force)
...
@@ -804,10 +836,39 @@ static void DSOUND_WaveQueue(DirectSoundDevice *device, BOOL force)
*/
*/
static
void
DSOUND_PerformMix
(
DirectSoundDevice
*
device
)
static
void
DSOUND_PerformMix
(
DirectSoundDevice
*
device
)
{
{
UINT64
clock_pos
,
clock_freq
,
pos_bytes
;
UINT
delta_frags
;
HRESULT
hr
;
TRACE
(
"(%p)
\n
"
,
device
);
TRACE
(
"(%p)
\n
"
,
device
);
/* **** */
/* **** */
EnterCriticalSection
(
&
(
device
->
mixlock
));
EnterCriticalSection
(
&
device
->
mixlock
);
hr
=
IAudioClock_GetFrequency
(
device
->
clock
,
&
clock_freq
);
if
(
FAILED
(
hr
)){
WARN
(
"GetFrequency failed: %08x
\n
"
,
hr
);
LeaveCriticalSection
(
&
device
->
mixlock
);
return
;
}
hr
=
IAudioClock_GetPosition
(
device
->
clock
,
&
clock_pos
,
NULL
);
if
(
FAILED
(
hr
)){
WARN
(
"GetCurrentPadding failed: %08x
\n
"
,
hr
);
LeaveCriticalSection
(
&
device
->
mixlock
);
return
;
}
pos_bytes
=
(
clock_pos
/
(
double
)
clock_freq
)
*
device
->
pwfx
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
delta_frags
=
(
pos_bytes
-
device
->
last_pos_bytes
)
/
device
->
fraglen
;
if
(
delta_frags
>
0
){
device
->
pwplay
+=
delta_frags
;
device
->
pwplay
%=
device
->
helfrags
;
device
->
pwqueue
-=
delta_frags
;
device
->
last_pos_bytes
=
pos_bytes
-
(
pos_bytes
%
device
->
fraglen
);
}
if
(
device
->
priolevel
!=
DSSCL_WRITEPRIMARY
)
{
if
(
device
->
priolevel
!=
DSSCL_WRITEPRIMARY
)
{
BOOL
recover
=
FALSE
,
all_stopped
=
FALSE
;
BOOL
recover
=
FALSE
,
all_stopped
=
FALSE
;
...
@@ -978,13 +1039,6 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser,
...
@@ -978,13 +1039,6 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser,
TRACE
(
"(%d,%d,0x%lx,0x%lx,0x%lx)
\n
"
,
timerID
,
msg
,
dwUser
,
dw1
,
dw2
);
TRACE
(
"(%d,%d,0x%lx,0x%lx,0x%lx)
\n
"
,
timerID
,
msg
,
dwUser
,
dw1
,
dw2
);
TRACE
(
"entering at %d
\n
"
,
start_time
);
TRACE
(
"entering at %d
\n
"
,
start_time
);
if
(
DSOUND_renderer
[
device
->
drvdesc
.
dnDevNode
]
!=
device
)
{
ERR
(
"dsound died without killing us?
\n
"
);
timeKillEvent
(
timerID
);
timeEndPeriod
(
DS_TIME_RES
);
return
;
}
RtlAcquireResourceShared
(
&
(
device
->
buffer_list_lock
),
TRUE
);
RtlAcquireResourceShared
(
&
(
device
->
buffer_list_lock
),
TRUE
);
if
(
device
->
ref
)
if
(
device
->
ref
)
...
@@ -995,37 +1049,3 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser,
...
@@ -995,37 +1049,3 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser,
end_time
=
GetTickCount
();
end_time
=
GetTickCount
();
TRACE
(
"completed processing at %d, duration = %d
\n
"
,
end_time
,
end_time
-
start_time
);
TRACE
(
"completed processing at %d, duration = %d
\n
"
,
end_time
,
end_time
-
start_time
);
}
}
void
CALLBACK
DSOUND_callback
(
HWAVEOUT
hwo
,
UINT
msg
,
DWORD_PTR
dwUser
,
DWORD_PTR
dw1
,
DWORD_PTR
dw2
)
{
DirectSoundDevice
*
device
=
(
DirectSoundDevice
*
)
dwUser
;
TRACE
(
"(%p,%x,%lx,%lx,%lx)
\n
"
,
hwo
,
msg
,
dwUser
,
dw1
,
dw2
);
TRACE
(
"entering at %d, msg=%08x(%s)
\n
"
,
GetTickCount
(),
msg
,
msg
==
MM_WOM_DONE
?
"MM_WOM_DONE"
:
msg
==
MM_WOM_CLOSE
?
"MM_WOM_CLOSE"
:
msg
==
MM_WOM_OPEN
?
"MM_WOM_OPEN"
:
"UNKNOWN"
);
/* check if packet completed from wave driver */
if
(
msg
==
MM_WOM_DONE
)
{
/* **** */
EnterCriticalSection
(
&
(
device
->
mixlock
));
TRACE
(
"done playing primary pos=%d
\n
"
,
device
->
pwplay
*
device
->
fraglen
);
/* update playpos */
device
->
pwplay
++
;
device
->
pwplay
%=
device
->
helfrags
;
/* sanity */
if
(
device
->
pwqueue
==
0
){
ERR
(
"Wave queue corrupted!
\n
"
);
}
/* update queue */
device
->
pwqueue
--
;
LeaveCriticalSection
(
&
(
device
->
mixlock
));
/* **** */
}
TRACE
(
"completed
\n
"
);
}
dlls/dsound/primary.c
View file @
e786998d
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include <stdarg.h>
#include <stdarg.h>
#define COBJMACROS
#define NONAMELESSSTRUCT
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#define NONAMELESSUNION
#include "windef.h"
#include "windef.h"
...
@@ -83,32 +84,86 @@ static void DSOUND_RecalcPrimary(DirectSoundDevice *device)
...
@@ -83,32 +84,86 @@ static void DSOUND_RecalcPrimary(DirectSoundDevice *device)
HRESULT
DSOUND_ReopenDevice
(
DirectSoundDevice
*
device
,
BOOL
forcewave
)
HRESULT
DSOUND_ReopenDevice
(
DirectSoundDevice
*
device
,
BOOL
forcewave
)
{
{
HRESULT
hres
=
DS_OK
;
HRESULT
hres
;
TRACE
(
"(%p, %d)
\n
"
,
device
,
forcewave
);
TRACE
(
"(%p, %d)
\n
"
,
device
,
forcewave
);
waveOutClose
(
device
->
hwo
);
if
(
device
->
client
){
IAudioClient_Release
(
device
->
client
);
device
->
client
=
NULL
;
}
if
(
device
->
render
){
IAudioRenderClient_Release
(
device
->
render
);
device
->
render
=
NULL
;
}
if
(
device
->
clock
){
IAudioClock_Release
(
device
->
clock
);
device
->
clock
=
NULL
;
}
if
(
device
->
volume
){
IAudioStreamVolume_Release
(
device
->
volume
);
device
->
volume
=
NULL
;
}
device
->
drvdesc
.
dwFlags
=
0
;
device
->
drvdesc
.
dwFlags
=
0
;
hres
=
IMMDevice_Activate
(
device
->
mmdevice
,
&
IID_IAudioClient
,
CLSCTX_INPROC_SERVER
,
NULL
,
(
void
**
)
&
device
->
client
);
if
(
FAILED
(
hres
)){
WARN
(
"Activate failed: %08x
\n
"
,
hres
);
return
hres
;
}
hres
=
mmErr
(
waveOutOpen
(
&
(
device
->
hwo
),
device
->
drvdesc
.
dnDevNode
,
/* buffer size = 200 * 100000 (100 ns) = 2.0 seconds */
device
->
pwfx
,
(
DWORD_PTR
)
DSOUND_callback
,
(
DWORD_PTR
)
device
,
hres
=
IAudioClient_Initialize
(
device
->
client
,
CALLBACK_FUNCTION
|
WAVE_MAPPED
));
AUDCLNT_SHAREMODE_SHARED
,
AUDCLNT_STREAMFLAGS_NOPERSIST
,
if
(
FAILED
(
hres
))
{
200
*
100000
,
50000
,
device
->
pwfx
,
NULL
);
WARN
(
"waveOutOpen failed: %08x
\n
"
,
hres
);
if
(
FAILED
(
hres
)){
IAudioClient_Release
(
device
->
client
);
device
->
client
=
NULL
;
WARN
(
"Initialize failed: %08x
\n
"
,
hres
);
return
hres
;
return
hres
;
}
}
hres
=
IAudioClient_GetService
(
device
->
client
,
&
IID_IAudioRenderClient
,
(
void
**
)
&
device
->
render
);
if
(
FAILED
(
hres
)){
IAudioClient_Release
(
device
->
client
);
device
->
client
=
NULL
;
WARN
(
"GetService failed: %08x
\n
"
,
hres
);
return
hres
;
return
hres
;
}
hres
=
IAudioClient_GetService
(
device
->
client
,
&
IID_IAudioClock
,
(
void
**
)
&
device
->
clock
);
if
(
FAILED
(
hres
)){
IAudioClient_Release
(
device
->
client
);
IAudioRenderClient_Release
(
device
->
render
);
device
->
client
=
NULL
;
device
->
render
=
NULL
;
WARN
(
"GetService failed: %08x
\n
"
,
hres
);
return
hres
;
}
hres
=
IAudioClient_GetService
(
device
->
client
,
&
IID_IAudioStreamVolume
,
(
void
**
)
&
device
->
volume
);
if
(
FAILED
(
hres
)){
IAudioClient_Release
(
device
->
client
);
IAudioRenderClient_Release
(
device
->
render
);
IAudioClock_Release
(
device
->
clock
);
device
->
client
=
NULL
;
device
->
render
=
NULL
;
device
->
clock
=
NULL
;
WARN
(
"GetService failed: %08x
\n
"
,
hres
);
return
hres
;
}
return
S_OK
;
}
}
static
HRESULT
DSOUND_PrimaryOpen
(
DirectSoundDevice
*
device
)
static
HRESULT
DSOUND_PrimaryOpen
(
DirectSoundDevice
*
device
)
{
{
DWORD
buflen
;
DWORD
buflen
;
HRESULT
err
=
DS_OK
;
LPBYTE
newbuf
;
LPBYTE
newbuf
;
LPWAVEHDR
headers
=
NULL
;
DWORD
overshot
;
unsigned
int
c
;
TRACE
(
"(%p)
\n
"
,
device
);
TRACE
(
"(%p)
\n
"
,
device
);
...
@@ -128,9 +183,6 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
...
@@ -128,9 +183,6 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
if
(
device
->
state
==
STATE_PLAYING
)
device
->
state
=
STATE_STARTING
;
if
(
device
->
state
==
STATE_PLAYING
)
device
->
state
=
STATE_STARTING
;
else
if
(
device
->
state
==
STATE_STOPPING
)
device
->
state
=
STATE_STOPPED
;
else
if
(
device
->
state
==
STATE_STOPPING
)
device
->
state
=
STATE_STOPPED
;
/* Start in pause mode, to allow buffers to get filled */
waveOutPause
(
device
->
hwo
);
TRACE
(
"desired buflen=%d, old buffer=%p
\n
"
,
buflen
,
device
->
buffer
);
TRACE
(
"desired buflen=%d, old buffer=%p
\n
"
,
buflen
,
device
->
buffer
);
/* reallocate emulated primary buffer */
/* reallocate emulated primary buffer */
...
@@ -146,70 +198,33 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
...
@@ -146,70 +198,33 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
}
}
DSOUND_RecalcPrimary
(
device
);
DSOUND_RecalcPrimary
(
device
);
if
(
device
->
pwave
)
headers
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
device
->
pwave
,
device
->
helfrags
*
sizeof
(
WAVEHDR
));
else
headers
=
HeapAlloc
(
GetProcessHeap
(),
0
,
device
->
helfrags
*
sizeof
(
WAVEHDR
));
if
(
!
headers
)
{
ERR
(
"failed to allocate wave headers
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
newbuf
);
DSOUND_RecalcPrimary
(
device
);
return
DSERR_OUTOFMEMORY
;
}
device
->
buffer
=
newbuf
;
device
->
buffer
=
newbuf
;
device
->
pwave
=
headers
;
/* prepare fragment headers */
for
(
c
=
0
;
c
<
device
->
helfrags
;
c
++
)
{
device
->
pwave
[
c
].
lpData
=
(
char
*
)
device
->
buffer
+
c
*
device
->
fraglen
;
device
->
pwave
[
c
].
dwBufferLength
=
device
->
fraglen
;
device
->
pwave
[
c
].
dwUser
=
(
DWORD_PTR
)
device
;
device
->
pwave
[
c
].
dwFlags
=
0
;
device
->
pwave
[
c
].
dwLoops
=
0
;
err
=
mmErr
(
waveOutPrepareHeader
(
device
->
hwo
,
&
device
->
pwave
[
c
],
sizeof
(
WAVEHDR
)));
if
(
err
!=
DS_OK
)
{
while
(
c
--
)
waveOutUnprepareHeader
(
device
->
hwo
,
&
device
->
pwave
[
c
],
sizeof
(
WAVEHDR
));
break
;
}
}
overshot
=
device
->
buflen
%
device
->
fraglen
;
TRACE
(
"fraglen=%d
\n
"
,
device
->
fraglen
);
/* sanity */
if
(
overshot
)
{
overshot
-=
overshot
%
device
->
pwfx
->
nBlockAlign
;
device
->
pwave
[
device
->
helfrags
-
1
].
dwBufferLength
+=
overshot
;
}
TRACE
(
"fraglen=%d, overshot=%d
\n
"
,
device
->
fraglen
,
overshot
);
device
->
mixfunction
=
mixfunctions
[
device
->
pwfx
->
wBitsPerSample
/
8
-
1
];
device
->
mixfunction
=
mixfunctions
[
device
->
pwfx
->
wBitsPerSample
/
8
-
1
];
device
->
normfunction
=
normfunctions
[
device
->
pwfx
->
wBitsPerSample
/
8
-
1
];
device
->
normfunction
=
normfunctions
[
device
->
pwfx
->
wBitsPerSample
/
8
-
1
];
FillMemory
(
device
->
buffer
,
device
->
buflen
,
(
device
->
pwfx
->
wBitsPerSample
==
8
)
?
128
:
0
);
FillMemory
(
device
->
buffer
,
device
->
buflen
,
(
device
->
pwfx
->
wBitsPerSample
==
8
)
?
128
:
0
);
FillMemory
(
device
->
mix_buffer
,
device
->
mix_buffer_len
,
0
);
FillMemory
(
device
->
mix_buffer
,
device
->
mix_buffer_len
,
0
);
device
->
pwplay
=
device
->
pwqueue
=
device
->
playpos
=
device
->
mixpos
=
0
;
device
->
last_pos_bytes
=
device
->
pwplay
=
device
->
pwqueue
=
device
->
playpos
=
device
->
mixpos
=
0
;
return
err
;
return
DS_OK
;
}
}
static
void
DSOUND_PrimaryClose
(
DirectSoundDevice
*
device
)
static
void
DSOUND_PrimaryClose
(
DirectSoundDevice
*
device
)
{
{
unsigned
c
;
HRESULT
hr
;
TRACE
(
"(%p)
\n
"
,
device
);
TRACE
(
"(%p)
\n
"
,
device
);
/* get out of CS when calling the wave system */
LeaveCriticalSection
(
&
(
device
->
mixlock
));
/* **** */
device
->
pwqueue
=
(
DWORD
)
-
1
;
/* resetting queues */
device
->
pwqueue
=
(
DWORD
)
-
1
;
/* resetting queues */
waveOutReset
(
device
->
hwo
);
for
(
c
=
0
;
c
<
device
->
helfrags
;
c
++
)
if
(
device
->
client
){
waveOutUnprepareHeader
(
device
->
hwo
,
&
device
->
pwave
[
c
],
sizeof
(
WAVEHDR
));
hr
=
IAudioClient_Stop
(
device
->
client
);
/* **** */
if
(
FAILED
(
hr
))
EnterCriticalSection
(
&
(
device
->
mixlock
));
WARN
(
"Stop failed: %08x
\n
"
,
hr
);
}
/* clear the queue */
/* clear the queue */
device
->
pwqueue
=
0
;
device
->
pwqueue
=
0
;
...
@@ -240,7 +255,6 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
...
@@ -240,7 +255,6 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
EnterCriticalSection
(
&
(
device
->
mixlock
));
EnterCriticalSection
(
&
(
device
->
mixlock
));
DSOUND_PrimaryClose
(
device
);
DSOUND_PrimaryClose
(
device
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
pwave
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
pwfx
);
HeapFree
(
GetProcessHeap
(),
0
,
device
->
pwfx
);
device
->
pwfx
=
NULL
;
device
->
pwfx
=
NULL
;
...
@@ -252,32 +266,32 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
...
@@ -252,32 +266,32 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
HRESULT
DSOUND_PrimaryPlay
(
DirectSoundDevice
*
device
)
HRESULT
DSOUND_PrimaryPlay
(
DirectSoundDevice
*
device
)
{
{
HRESULT
err
=
DS_OK
;
HRESULT
hr
;
TRACE
(
"(%p)
\n
"
,
device
);
TRACE
(
"(%p)
\n
"
,
device
);
err
=
mmErr
(
waveOutRestart
(
device
->
hwo
));
hr
=
IAudioClient_Start
(
device
->
client
);
if
(
err
!=
DS_OK
)
if
(
FAILED
(
hr
)){
WARN
(
"waveOutRestart failed
\n
"
);
WARN
(
"Start failed: %08x
\n
"
,
hr
);
return
hr
;
}
return
err
;
return
DS_OK
;
}
}
HRESULT
DSOUND_PrimaryStop
(
DirectSoundDevice
*
device
)
HRESULT
DSOUND_PrimaryStop
(
DirectSoundDevice
*
device
)
{
{
HRESULT
err
=
DS_OK
;
HRESULT
hr
;
TRACE
(
"(%p)
\n
"
,
device
);
/* don't call the wave system with the lock set */
LeaveCriticalSection
(
&
(
device
->
mixlock
));
err
=
mmErr
(
waveOutPause
(
device
->
hwo
));
TRACE
(
"(%p)
\n
"
,
device
);
EnterCriticalSection
(
&
(
device
->
mixlock
));
if
(
err
!=
DS_OK
)
hr
=
IAudioClient_Stop
(
device
->
client
);
WARN
(
"waveOutPause failed
\n
"
);
if
(
FAILED
(
hr
)){
WARN
(
"Stop failed: %08x
\n
"
,
hr
);
return
hr
;
}
return
err
;
return
DS_OK
;
}
}
HRESULT
DSOUND_PrimaryGetPosition
(
DirectSoundDevice
*
device
,
LPDWORD
playpos
,
LPDWORD
writepos
)
HRESULT
DSOUND_PrimaryGetPosition
(
DirectSoundDevice
*
device
,
LPDWORD
playpos
,
LPDWORD
writepos
)
...
@@ -331,15 +345,15 @@ LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex)
...
@@ -331,15 +345,15 @@ LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex)
return
pwfx
;
return
pwfx
;
}
}
HRESULT
primarybuffer_SetFormat
(
DirectSoundDevice
*
device
,
LPCWAVEFORMATEX
wfex
)
HRESULT
primarybuffer_SetFormat
(
DirectSoundDevice
*
device
,
LPCWAVEFORMATEX
passed_fmt
)
{
{
HRESULT
err
=
DSERR_BUFFERLOST
;
HRESULT
err
=
DSERR_BUFFERLOST
;
int
i
;
int
i
;
DWORD
nSamplesPerSec
,
bpp
,
chans
;
WAVEFORMATEX
*
old_fmt
;
LPWAVEFORMATEX
oldpwf
x
;
WAVEFORMATEXTENSIBLE
*
fmte
x
;
BOOL
forced
=
device
->
priolevel
==
DSSCL_WRITEPRIMARY
;
BOOL
forced
=
(
device
->
priolevel
==
DSSCL_WRITEPRIMARY
)
;
TRACE
(
"(%p,%p)
\n
"
,
device
,
wfex
);
TRACE
(
"(%p,%p)
\n
"
,
device
,
passed_fmt
);
if
(
device
->
priolevel
==
DSSCL_NORMAL
)
{
if
(
device
->
priolevel
==
DSSCL_NORMAL
)
{
WARN
(
"failed priority check!
\n
"
);
WARN
(
"failed priority check!
\n
"
);
...
@@ -347,29 +361,26 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex)
...
@@ -347,29 +361,26 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex)
}
}
/* Let's be pedantic! */
/* Let's be pedantic! */
if
(
wfex
==
NULL
)
{
if
(
passed_fmt
==
NULL
)
{
WARN
(
"invalid parameter:
wfex
==NULL!
\n
"
);
WARN
(
"invalid parameter:
passed_fmt
==NULL!
\n
"
);
return
DSERR_INVALIDPARAM
;
return
DSERR_INVALIDPARAM
;
}
}
TRACE
(
"(formattag=0x%04x,chans=%d,samplerate=%d,"
TRACE
(
"(formattag=0x%04x,chans=%d,samplerate=%d,"
"bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)
\n
"
,
"bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)
\n
"
,
wfex
->
wFormatTag
,
wfex
->
nChannels
,
wfex
->
nSamplesPerSec
,
passed_fmt
->
wFormatTag
,
passed_fmt
->
nChannels
,
passed_fmt
->
nSamplesPerSec
,
wfex
->
nAvgBytesPerSec
,
wfex
->
nBlockAlign
,
passed_fmt
->
nAvgBytesPerSec
,
passed_fmt
->
nBlockAlign
,
wfex
->
wBitsPerSample
,
wfex
->
cbSize
);
passed_fmt
->
wBitsPerSample
,
passed_fmt
->
cbSize
);
/* **** */
/* **** */
RtlAcquireResourceExclusive
(
&
(
device
->
buffer_list_lock
),
TRUE
);
RtlAcquireResourceExclusive
(
&
(
device
->
buffer_list_lock
),
TRUE
);
EnterCriticalSection
(
&
(
device
->
mixlock
));
EnterCriticalSection
(
&
(
device
->
mixlock
));
nSamplesPerSec
=
device
->
pwfx
->
nSamplesPerSec
;
old_fmt
=
device
->
pwfx
;
bpp
=
device
->
pwfx
->
wBitsPerSample
;
device
->
pwfx
=
DSOUND_CopyFormat
(
passed_fmt
);
chans
=
device
->
pwfx
->
nChannels
;
fmtex
=
(
WAVEFORMATEXTENSIBLE
*
)
device
->
pwfx
;
oldpwfx
=
device
->
pwfx
;
device
->
pwfx
=
DSOUND_CopyFormat
(
wfex
);
if
(
device
->
pwfx
==
NULL
)
{
if
(
device
->
pwfx
==
NULL
)
{
device
->
pwfx
=
old
pwfx
;
device
->
pwfx
=
old
_fmt
;
old
pwfx
=
NULL
;
old
_fmt
=
NULL
;
err
=
DSERR_OUTOFMEMORY
;
err
=
DSERR_OUTOFMEMORY
;
goto
done
;
goto
done
;
}
}
...
@@ -377,21 +388,97 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex)
...
@@ -377,21 +388,97 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex)
DSOUND_PrimaryClose
(
device
);
DSOUND_PrimaryClose
(
device
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
FAILED
(
err
))
if
(
SUCCEEDED
(
err
))
{
goto
opened
;
WARN
(
"DSOUND_ReopenDevice failed: %08x
\n
"
,
err
);
goto
done
;
/* requested format failed, so try others */
if
(
device
->
pwfx
->
wFormatTag
==
WAVE_FORMAT_IEEE_FLOAT
){
device
->
pwfx
->
wFormatTag
=
WAVE_FORMAT_PCM
;
device
->
pwfx
->
wBitsPerSample
=
32
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
}
}
if
(
device
->
pwfx
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
&&
IsEqualGUID
(
&
fmtex
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)){
fmtex
->
SubFormat
=
KSDATAFORMAT_SUBTYPE_PCM
;
device
->
pwfx
->
wBitsPerSample
=
32
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
}
device
->
pwfx
->
wBitsPerSample
=
32
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
device
->
pwfx
->
wBitsPerSample
=
16
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
device
->
pwfx
->
wBitsPerSample
=
8
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
device
->
pwfx
->
nChannels
=
(
passed_fmt
->
nChannels
==
2
)
?
1
:
2
;
device
->
pwfx
->
wBitsPerSample
=
passed_fmt
->
wBitsPerSample
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
device
->
pwfx
->
wBitsPerSample
=
32
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
device
->
pwfx
->
wBitsPerSample
=
16
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
device
->
pwfx
->
wBitsPerSample
=
8
;
device
->
pwfx
->
nAvgBytesPerSec
=
passed_fmt
->
nSamplesPerSec
*
device
->
pwfx
->
nBlockAlign
;
device
->
pwfx
->
nBlockAlign
=
passed_fmt
->
nChannels
*
(
device
->
pwfx
->
wBitsPerSample
/
8
);
err
=
DSOUND_ReopenDevice
(
device
,
FALSE
);
if
(
SUCCEEDED
(
err
))
goto
opened
;
WARN
(
"No formats could be opened
\n
"
);
goto
done
;
opened:
err
=
DSOUND_PrimaryOpen
(
device
);
err
=
DSOUND_PrimaryOpen
(
device
);
if
(
err
!=
DS_OK
)
{
if
(
err
!=
DS_OK
)
{
WARN
(
"DSOUND_PrimaryOpen failed
\n
"
);
WARN
(
"DSOUND_PrimaryOpen failed
\n
"
);
goto
done
;
goto
done
;
}
}
if
(
wfex
->
nSamplesPerSec
/
100
!=
device
->
pwfx
->
nSamplesPerSec
/
100
&&
forced
&&
device
->
buffer
)
if
(
passed_fmt
->
nSamplesPerSec
/
100
!=
device
->
pwfx
->
nSamplesPerSec
/
100
&&
forced
&&
device
->
buffer
)
{
{
DSOUND_PrimaryClose
(
device
);
DSOUND_PrimaryClose
(
device
);
device
->
pwfx
->
nSamplesPerSec
=
wfex
->
nSamplesPerSec
;
device
->
pwfx
->
nSamplesPerSec
=
passed_fmt
->
nSamplesPerSec
;
err
=
DSOUND_ReopenDevice
(
device
,
TRUE
);
err
=
DSOUND_ReopenDevice
(
device
,
TRUE
);
if
(
FAILED
(
err
))
if
(
FAILED
(
err
))
WARN
(
"DSOUND_ReopenDevice(2) failed: %08x
\n
"
,
err
);
WARN
(
"DSOUND_ReopenDevice(2) failed: %08x
\n
"
,
err
);
...
@@ -405,7 +492,9 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex)
...
@@ -405,7 +492,9 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex)
device
->
mixfunction
=
mixfunctions
[
device
->
pwfx
->
wBitsPerSample
/
8
-
1
];
device
->
mixfunction
=
mixfunctions
[
device
->
pwfx
->
wBitsPerSample
/
8
-
1
];
device
->
normfunction
=
normfunctions
[
device
->
pwfx
->
wBitsPerSample
/
8
-
1
];
device
->
normfunction
=
normfunctions
[
device
->
pwfx
->
wBitsPerSample
/
8
-
1
];
if
(
nSamplesPerSec
!=
device
->
pwfx
->
nSamplesPerSec
||
bpp
!=
device
->
pwfx
->
wBitsPerSample
||
chans
!=
device
->
pwfx
->
nChannels
)
{
if
(
old_fmt
->
nSamplesPerSec
!=
device
->
pwfx
->
nSamplesPerSec
||
old_fmt
->
wBitsPerSample
!=
device
->
pwfx
->
wBitsPerSample
||
old_fmt
->
nChannels
!=
device
->
pwfx
->
nChannels
)
{
IDirectSoundBufferImpl
**
dsb
=
device
->
buffers
;
IDirectSoundBufferImpl
**
dsb
=
device
->
buffers
;
for
(
i
=
0
;
i
<
device
->
nrofbuffers
;
i
++
,
dsb
++
)
{
for
(
i
=
0
;
i
<
device
->
nrofbuffers
;
i
++
,
dsb
++
)
{
/* **** */
/* **** */
...
@@ -426,7 +515,7 @@ done:
...
@@ -426,7 +515,7 @@ done:
RtlReleaseResource
(
&
(
device
->
buffer_list_lock
));
RtlReleaseResource
(
&
(
device
->
buffer_list_lock
));
/* **** */
/* **** */
HeapFree
(
GetProcessHeap
(),
0
,
old
pwfx
);
HeapFree
(
GetProcessHeap
(),
0
,
old
_fmt
);
return
err
;
return
err
;
}
}
...
@@ -455,8 +544,9 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
...
@@ -455,8 +544,9 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
)
{
)
{
IDirectSoundBufferImpl
*
This
=
impl_from_IDirectSoundBuffer
(
iface
);
IDirectSoundBufferImpl
*
This
=
impl_from_IDirectSoundBuffer
(
iface
);
DirectSoundDevice
*
device
=
This
->
device
;
DirectSoundDevice
*
device
=
This
->
device
;
DWORD
ampfactors
;
HRESULT
hr
;
HRESULT
hres
=
DS_OK
;
float
lvol
,
rvol
;
TRACE
(
"(%p,%d)
\n
"
,
iface
,
vol
);
TRACE
(
"(%p,%d)
\n
"
,
iface
,
vol
);
if
(
!
(
This
->
dsbd
.
dwFlags
&
DSBCAPS_CTRLVOLUME
))
{
if
(
!
(
This
->
dsbd
.
dwFlags
&
DSBCAPS_CTRLVOLUME
))
{
...
@@ -470,23 +560,55 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
...
@@ -470,23 +560,55 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
}
}
/* **** */
/* **** */
EnterCriticalSection
(
&
(
device
->
mixlock
));
EnterCriticalSection
(
&
device
->
mixlock
);
hr
=
IAudioStreamVolume_GetChannelVolume
(
device
->
volume
,
0
,
&
lvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"GetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
if
(
device
->
pwfx
->
nChannels
>
1
){
hr
=
IAudioStreamVolume_GetChannelVolume
(
device
->
volume
,
1
,
&
rvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"GetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
}
else
rvol
=
1
;
device
->
volpan
.
dwTotalLeftAmpFactor
=
((
UINT16
)(
lvol
*
(
DWORD
)
0xFFFF
));
device
->
volpan
.
dwTotalRightAmpFactor
=
((
UINT16
)(
rvol
*
(
DWORD
)
0xFFFF
));
waveOutGetVolume
(
device
->
hwo
,
&
ampfactors
);
device
->
volpan
.
dwTotalLeftAmpFactor
=
ampfactors
&
0xffff
;
device
->
volpan
.
dwTotalRightAmpFactor
=
ampfactors
>>
16
;
DSOUND_AmpFactorToVolPan
(
&
device
->
volpan
);
DSOUND_AmpFactorToVolPan
(
&
device
->
volpan
);
if
(
vol
!=
device
->
volpan
.
lVolume
)
{
if
(
vol
!=
device
->
volpan
.
lVolume
)
{
device
->
volpan
.
lVolume
=
vol
;
device
->
volpan
.
lVolume
=
vol
;
DSOUND_RecalcVolPan
(
&
device
->
volpan
);
DSOUND_RecalcVolPan
(
&
device
->
volpan
);
ampfactors
=
(
device
->
volpan
.
dwTotalLeftAmpFactor
&
0xffff
)
|
(
device
->
volpan
.
dwTotalRightAmpFactor
<<
16
);
lvol
=
(
float
)((
DWORD
)(
device
->
volpan
.
dwTotalLeftAmpFactor
&
0xFFFF
)
/
(
float
)
0xFFFF
);
waveOutSetVolume
(
device
->
hwo
,
ampfactors
);
hr
=
IAudioStreamVolume_SetChannelVolume
(
device
->
volume
,
0
,
lvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"SetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
if
(
device
->
pwfx
->
nChannels
>
1
){
rvol
=
(
float
)((
DWORD
)(
device
->
volpan
.
dwTotalRightAmpFactor
&
0xFFFF
)
/
(
float
)
0xFFFF
);
hr
=
IAudioStreamVolume_SetChannelVolume
(
device
->
volume
,
1
,
rvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"SetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
}
}
}
LeaveCriticalSection
(
&
(
device
->
mixlock
));
LeaveCriticalSection
(
&
(
device
->
mixlock
));
/* **** */
/* **** */
return
hres
;
return
DS_OK
;
}
}
static
HRESULT
WINAPI
PrimaryBufferImpl_GetVolume
(
static
HRESULT
WINAPI
PrimaryBufferImpl_GetVolume
(
...
@@ -494,7 +616,8 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
...
@@ -494,7 +616,8 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
)
{
)
{
IDirectSoundBufferImpl
*
This
=
impl_from_IDirectSoundBuffer
(
iface
);
IDirectSoundBufferImpl
*
This
=
impl_from_IDirectSoundBuffer
(
iface
);
DirectSoundDevice
*
device
=
This
->
device
;
DirectSoundDevice
*
device
=
This
->
device
;
DWORD
ampfactors
;
float
lvol
,
rvol
;
HRESULT
hr
;
TRACE
(
"(%p,%p)
\n
"
,
iface
,
vol
);
TRACE
(
"(%p,%p)
\n
"
,
iface
,
vol
);
if
(
!
(
This
->
dsbd
.
dwFlags
&
DSBCAPS_CTRLVOLUME
))
{
if
(
!
(
This
->
dsbd
.
dwFlags
&
DSBCAPS_CTRLVOLUME
))
{
...
@@ -507,12 +630,33 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
...
@@ -507,12 +630,33 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
return
DSERR_INVALIDPARAM
;
return
DSERR_INVALIDPARAM
;
}
}
waveOutGetVolume
(
device
->
hwo
,
&
ampfactors
);
EnterCriticalSection
(
&
device
->
mixlock
);
device
->
volpan
.
dwTotalLeftAmpFactor
=
ampfactors
&
0xffff
;
device
->
volpan
.
dwTotalRightAmpFactor
=
ampfactors
>>
16
;
hr
=
IAudioStreamVolume_GetChannelVolume
(
device
->
volume
,
0
,
&
lvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"GetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
if
(
device
->
pwfx
->
nChannels
>
1
){
hr
=
IAudioStreamVolume_GetChannelVolume
(
device
->
volume
,
1
,
&
rvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"GetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
}
else
rvol
=
1
;
device
->
volpan
.
dwTotalLeftAmpFactor
=
((
UINT16
)(
lvol
*
(
DWORD
)
0xFFFF
));
device
->
volpan
.
dwTotalRightAmpFactor
=
((
UINT16
)(
rvol
*
(
DWORD
)
0xFFFF
));
DSOUND_AmpFactorToVolPan
(
&
device
->
volpan
);
DSOUND_AmpFactorToVolPan
(
&
device
->
volpan
);
*
vol
=
device
->
volpan
.
lVolume
;
*
vol
=
device
->
volpan
.
lVolume
;
LeaveCriticalSection
(
&
device
->
mixlock
);
return
DS_OK
;
return
DS_OK
;
}
}
...
@@ -778,8 +922,8 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan(
...
@@ -778,8 +922,8 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan(
)
{
)
{
IDirectSoundBufferImpl
*
This
=
impl_from_IDirectSoundBuffer
(
iface
);
IDirectSoundBufferImpl
*
This
=
impl_from_IDirectSoundBuffer
(
iface
);
DirectSoundDevice
*
device
=
This
->
device
;
DirectSoundDevice
*
device
=
This
->
device
;
DWORD
ampfactors
;
float
lvol
,
rvol
;
HRESULT
hres
=
DS_OK
;
HRESULT
hr
;
TRACE
(
"(%p,%d)
\n
"
,
iface
,
pan
);
TRACE
(
"(%p,%d)
\n
"
,
iface
,
pan
);
if
(
!
(
This
->
dsbd
.
dwFlags
&
DSBCAPS_CTRLPAN
))
{
if
(
!
(
This
->
dsbd
.
dwFlags
&
DSBCAPS_CTRLPAN
))
{
...
@@ -793,23 +937,56 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan(
...
@@ -793,23 +937,56 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan(
}
}
/* **** */
/* **** */
EnterCriticalSection
(
&
(
device
->
mixlock
));
EnterCriticalSection
(
&
device
->
mixlock
);
hr
=
IAudioStreamVolume_GetChannelVolume
(
device
->
volume
,
0
,
&
lvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"GetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
if
(
device
->
pwfx
->
nChannels
>
1
){
hr
=
IAudioStreamVolume_GetChannelVolume
(
device
->
volume
,
1
,
&
rvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"GetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
}
else
rvol
=
1
;
device
->
volpan
.
dwTotalLeftAmpFactor
=
((
UINT16
)(
lvol
*
(
DWORD
)
0xFFFF
));
device
->
volpan
.
dwTotalRightAmpFactor
=
((
UINT16
)(
rvol
*
(
DWORD
)
0xFFFF
));
waveOutGetVolume
(
device
->
hwo
,
&
ampfactors
);
device
->
volpan
.
dwTotalLeftAmpFactor
=
ampfactors
&
0xffff
;
device
->
volpan
.
dwTotalRightAmpFactor
=
ampfactors
>>
16
;
DSOUND_AmpFactorToVolPan
(
&
device
->
volpan
);
DSOUND_AmpFactorToVolPan
(
&
device
->
volpan
);
if
(
pan
!=
device
->
volpan
.
lPan
)
{
if
(
pan
!=
device
->
volpan
.
lPan
)
{
device
->
volpan
.
lPan
=
pan
;
device
->
volpan
.
lPan
=
pan
;
DSOUND_RecalcVolPan
(
&
device
->
volpan
);
DSOUND_RecalcVolPan
(
&
device
->
volpan
);
ampfactors
=
(
device
->
volpan
.
dwTotalLeftAmpFactor
&
0xffff
)
|
(
device
->
volpan
.
dwTotalRightAmpFactor
<<
16
);
waveOutSetVolume
(
device
->
hwo
,
ampfactors
);
lvol
=
(
float
)((
DWORD
)(
device
->
volpan
.
dwTotalLeftAmpFactor
&
0xFFFF
)
/
(
float
)
0xFFFF
);
hr
=
IAudioStreamVolume_SetChannelVolume
(
device
->
volume
,
0
,
lvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"SetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
}
LeaveCriticalSection
(
&
(
device
->
mixlock
));
if
(
device
->
pwfx
->
nChannels
>
1
){
rvol
=
(
float
)((
DWORD
)(
device
->
volpan
.
dwTotalRightAmpFactor
&
0xFFFF
)
/
(
float
)
0xFFFF
);
hr
=
IAudioStreamVolume_SetChannelVolume
(
device
->
volume
,
1
,
rvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"SetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
}
}
LeaveCriticalSection
(
&
device
->
mixlock
);
/* **** */
/* **** */
return
hres
;
return
DS_OK
;
}
}
static
HRESULT
WINAPI
PrimaryBufferImpl_GetPan
(
static
HRESULT
WINAPI
PrimaryBufferImpl_GetPan
(
...
@@ -817,7 +994,8 @@ static HRESULT WINAPI PrimaryBufferImpl_GetPan(
...
@@ -817,7 +994,8 @@ static HRESULT WINAPI PrimaryBufferImpl_GetPan(
)
{
)
{
IDirectSoundBufferImpl
*
This
=
impl_from_IDirectSoundBuffer
(
iface
);
IDirectSoundBufferImpl
*
This
=
impl_from_IDirectSoundBuffer
(
iface
);
DirectSoundDevice
*
device
=
This
->
device
;
DirectSoundDevice
*
device
=
This
->
device
;
DWORD
ampfactors
;
float
lvol
,
rvol
;
HRESULT
hr
;
TRACE
(
"(%p,%p)
\n
"
,
iface
,
pan
);
TRACE
(
"(%p,%p)
\n
"
,
iface
,
pan
);
if
(
!
(
This
->
dsbd
.
dwFlags
&
DSBCAPS_CTRLPAN
))
{
if
(
!
(
This
->
dsbd
.
dwFlags
&
DSBCAPS_CTRLPAN
))
{
...
@@ -830,11 +1008,33 @@ static HRESULT WINAPI PrimaryBufferImpl_GetPan(
...
@@ -830,11 +1008,33 @@ static HRESULT WINAPI PrimaryBufferImpl_GetPan(
return
DSERR_INVALIDPARAM
;
return
DSERR_INVALIDPARAM
;
}
}
waveOutGetVolume
(
device
->
hwo
,
&
ampfactors
);
EnterCriticalSection
(
&
device
->
mixlock
);
device
->
volpan
.
dwTotalLeftAmpFactor
=
ampfactors
&
0xffff
;
device
->
volpan
.
dwTotalRightAmpFactor
=
ampfactors
>>
16
;
hr
=
IAudioStreamVolume_GetChannelVolume
(
device
->
volume
,
0
,
&
lvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"GetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
if
(
device
->
pwfx
->
nChannels
>
1
){
hr
=
IAudioStreamVolume_GetChannelVolume
(
device
->
volume
,
1
,
&
rvol
);
if
(
FAILED
(
hr
)){
LeaveCriticalSection
(
&
device
->
mixlock
);
WARN
(
"GetChannelVolume failed: %08x
\n
"
,
hr
);
return
hr
;
}
}
else
rvol
=
1
;
device
->
volpan
.
dwTotalLeftAmpFactor
=
((
UINT16
)(
lvol
*
(
DWORD
)
0xFFFF
));
device
->
volpan
.
dwTotalRightAmpFactor
=
((
UINT16
)(
rvol
*
(
DWORD
)
0xFFFF
));
DSOUND_AmpFactorToVolPan
(
&
device
->
volpan
);
DSOUND_AmpFactorToVolPan
(
&
device
->
volpan
);
*
pan
=
device
->
volpan
.
lPan
;
*
pan
=
device
->
volpan
.
lPan
;
LeaveCriticalSection
(
&
device
->
mixlock
);
return
DS_OK
;
return
DS_OK
;
}
}
...
...
dlls/mmdevapi/tests/dependency.c
View file @
e786998d
...
@@ -71,7 +71,7 @@ START_TEST(dependency)
...
@@ -71,7 +71,7 @@ START_TEST(dependency)
ok
(
!
GetModuleHandle
(
"dsound.dll"
),
"dsound.dll was already loaded!
\n
"
);
ok
(
!
GetModuleHandle
(
"dsound.dll"
),
"dsound.dll was already loaded!
\n
"
);
hr
=
IMMDevice_Activate
(
dev
,
&
IID_IDirectSound8
,
CLSCTX_INPROC_SERVER
,
NULL
,
(
void
**
)
&
ds8
);
hr
=
IMMDevice_Activate
(
dev
,
&
IID_IDirectSound8
,
CLSCTX_INPROC_SERVER
,
NULL
,
(
void
**
)
&
ds8
);
todo_wine
ok
(
hr
==
S_OK
,
"Activating ds8 interface failed: 0x%08x
\n
"
,
hr
);
ok
(
hr
==
S_OK
,
"Activating ds8 interface failed: 0x%08x
\n
"
,
hr
);
if
(
hr
==
S_OK
)
if
(
hr
==
S_OK
)
{
{
ok
(
GetModuleHandle
(
"dsound.dll"
)
!=
NULL
,
"dsound.dll not loaded!
\n
"
);
ok
(
GetModuleHandle
(
"dsound.dll"
)
!=
NULL
,
"dsound.dll not loaded!
\n
"
);
...
...
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