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
8f03c51e
Commit
8f03c51e
authored
Dec 27, 2012
by
Andrew Eikum
Committed by
Alexandre Julliard
Dec 28, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winmm: Reroute WAVE_MAPPER devices as the default device changes.
parent
bc5d953f
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
252 additions
and
123 deletions
+252
-123
waveform.c
dlls/winmm/waveform.c
+252
-123
No files found.
dlls/winmm/waveform.c
View file @
8f03c51e
...
@@ -97,6 +97,7 @@ typedef struct _WINMM_Device {
...
@@ -97,6 +97,7 @@ typedef struct _WINMM_Device {
IAudioClock
*
clock
;
IAudioClock
*
clock
;
IAudioStreamVolume
*
volume
;
IAudioStreamVolume
*
volume
;
WAVEFORMATEX
*
orig_fmt
;
HACMSTREAM
acm_handle
;
HACMSTREAM
acm_handle
;
ACMSTREAMHEADER
acm_hdr
;
ACMSTREAMHEADER
acm_hdr
;
UINT32
acm_offs
;
UINT32
acm_offs
;
...
@@ -106,6 +107,7 @@ typedef struct _WINMM_Device {
...
@@ -106,6 +107,7 @@ typedef struct _WINMM_Device {
BOOL
stopped
;
BOOL
stopped
;
DWORD
loop_counter
;
DWORD
loop_counter
;
UINT32
bytes_per_frame
,
samples_per_sec
,
ofs_bytes
,
played_frames
;
UINT32
bytes_per_frame
,
samples_per_sec
,
ofs_bytes
,
played_frames
;
UINT32
remainder_frames
;
/* header chunk frames already played when a device switch occured */
/* stored in frames of sample rate, *not* AC::GetFrequency */
/* stored in frames of sample rate, *not* AC::GetFrequency */
UINT64
last_clock_pos
;
UINT64
last_clock_pos
;
...
@@ -172,6 +174,7 @@ typedef struct _WINMM_OpenInfo {
...
@@ -172,6 +174,7 @@ typedef struct _WINMM_OpenInfo {
DWORD_PTR
callback
;
DWORD_PTR
callback
;
DWORD_PTR
cb_user
;
DWORD_PTR
cb_user
;
DWORD
flags
;
DWORD
flags
;
BOOL
reset
;
}
WINMM_OpenInfo
;
}
WINMM_OpenInfo
;
typedef
struct
_WINMM_ControlDetails
{
typedef
struct
_WINMM_ControlDetails
{
...
@@ -191,6 +194,7 @@ static LRESULT WOD_Open(WINMM_OpenInfo *info);
...
@@ -191,6 +194,7 @@ static LRESULT WOD_Open(WINMM_OpenInfo *info);
static
LRESULT
WOD_Close
(
HWAVEOUT
hwave
);
static
LRESULT
WOD_Close
(
HWAVEOUT
hwave
);
static
LRESULT
WID_Open
(
WINMM_OpenInfo
*
info
);
static
LRESULT
WID_Open
(
WINMM_OpenInfo
*
info
);
static
LRESULT
WID_Close
(
HWAVEIN
hwave
);
static
LRESULT
WID_Close
(
HWAVEIN
hwave
);
static
MMRESULT
WINMM_BeginPlaying
(
WINMM_Device
*
device
);
void
WINMM_DeleteWaveform
(
void
)
void
WINMM_DeleteWaveform
(
void
)
{
{
...
@@ -273,14 +277,10 @@ static inline void WINMM_DecomposeHWAVE(HWAVE hwave, UINT *mmdevice_index,
...
@@ -273,14 +277,10 @@ static inline void WINMM_DecomposeHWAVE(HWAVE hwave, UINT *mmdevice_index,
*
junk
=
l
>>
15
;
*
junk
=
l
>>
15
;
}
}
static
void
WINMM_InitDevice
(
WINMM_Device
*
device
,
static
void
WINMM_InitDevice
(
WINMM_Device
*
device
)
WINMM_MMDevice
*
parent
,
HWAVE
hwave
)
{
{
InitializeCriticalSection
(
&
device
->
lock
);
InitializeCriticalSection
(
&
device
->
lock
);
device
->
lock
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": WINMM_Device.lock"
);
device
->
lock
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": WINMM_Device.lock"
);
device
->
handle
=
hwave
;
device
->
parent
=
parent
;
}
}
static
inline
WINMM_MMDevice
*
read_map
(
WINMM_MMDevice
**
map
,
UINT
index
)
static
inline
WINMM_MMDevice
*
read_map
(
WINMM_MMDevice
**
map
,
UINT
index
)
...
@@ -312,14 +312,16 @@ static WINMM_Device *WINMM_FindUnusedDevice(WINMM_Device **devices,
...
@@ -312,14 +312,16 @@ static WINMM_Device *WINMM_FindUnusedDevice(WINMM_Device **devices,
if
(
!
device
)
if
(
!
device
)
return
NULL
;
return
NULL
;
WINMM_InitDevice
(
device
,
parent
,
WINMM_InitDevice
(
device
);
WINMM_MakeHWAVE
(
internal_index
,
is_out
,
i
));
EnterCriticalSection
(
&
device
->
lock
);
EnterCriticalSection
(
&
device
->
lock
);
}
else
}
else
EnterCriticalSection
(
&
device
->
lock
);
EnterCriticalSection
(
&
device
->
lock
);
if
(
!
device
->
open
){
if
(
!
device
->
open
){
device
->
handle
=
WINMM_MakeHWAVE
(
internal_index
,
is_out
,
i
);
device
->
parent
=
parent
;
device
->
open
=
TRUE
;
device
->
open
=
TRUE
;
return
device
;
return
device
;
}
}
...
@@ -678,38 +680,20 @@ static HRESULT WINAPI notif_OnDeviceRemoved(IMMNotificationClient *iface,
...
@@ -678,38 +680,20 @@ static HRESULT WINAPI notif_OnDeviceRemoved(IMMNotificationClient *iface,
return
S_OK
;
return
S_OK
;
}
}
static
HRESULT
WINAPI
notif_OnDefaultDeviceChanged
(
IMMNotificationClient
*
iface
,
static
HRESULT
update_mapping
(
WINMM_MMDevice
***
map
,
UINT
count
,
EDataFlow
flow
,
ERole
role
,
const
WCHAR
*
device
_id
)
const
WCHAR
*
default
_id
)
{
{
WINMM_MMDevice
***
map
;
WINMM_MMDevice
*
prev
;
WINMM_MMDevice
*
prev
;
UINT
count
,
i
;
UINT
i
;
TRACE
(
"%u %u %s
\n
"
,
flow
,
role
,
wine_dbgstr_w
(
device_id
));
if
(
role
!=
eConsole
)
return
S_OK
;
EnterCriticalSection
(
&
g_devthread_lock
);
if
(
flow
==
eRender
){
map
=
&
g_out_map
;
count
=
g_outmmdevices_count
;
}
else
{
map
=
&
g_in_map
;
count
=
g_inmmdevices_count
;
}
prev
=
(
*
map
)[
0
];
prev
=
(
*
map
)[
0
];
for
(
i
=
0
;
i
<
count
;
++
i
){
for
(
i
=
0
;
i
<
count
;
++
i
){
WINMM_MMDevice
*
tmp
;
WINMM_MMDevice
*
tmp
;
if
(
!
lstrcmpW
((
*
map
)[
i
]
->
dev_id
,
de
vice
_id
)){
if
(
!
lstrcmpW
((
*
map
)[
i
]
->
dev_id
,
de
fault
_id
)){
(
*
map
)[
0
]
=
(
*
map
)[
i
];
(
*
map
)[
0
]
=
(
*
map
)[
i
];
(
*
map
)[
i
]
=
prev
;
(
*
map
)[
i
]
=
prev
;
LeaveCriticalSection
(
&
g_devthread_lock
);
return
S_OK
;
return
S_OK
;
}
}
...
@@ -721,6 +705,121 @@ static HRESULT WINAPI notif_OnDefaultDeviceChanged(IMMNotificationClient *iface,
...
@@ -721,6 +705,121 @@ static HRESULT WINAPI notif_OnDefaultDeviceChanged(IMMNotificationClient *iface,
WARN
(
"Couldn't find new default device! Rearranged map for no reason.
\n
"
);
WARN
(
"Couldn't find new default device! Rearranged map for no reason.
\n
"
);
(
*
map
)[
0
]
=
prev
;
(
*
map
)[
0
]
=
prev
;
return
S_FALSE
;
}
static
HRESULT
reroute_mapper_device
(
WINMM_Device
*
device
,
BOOL
is_out
)
{
WINMM_OpenInfo
info
;
BOOL
stopped
;
MMRESULT
mr
;
HRESULT
hr
;
UINT64
clock_freq
,
clock_pos
;
TRACE
(
"rerouting device %p
\n
"
,
device
->
handle
);
EnterCriticalSection
(
&
device
->
lock
);
if
(
!
device
->
open
||
device
->
acm_handle
){
/* Windows 7 doesn't re-route ACM devices, so we don't either.
* Seems to be because of the data waveXxxPrepareHeader allocates. */
LeaveCriticalSection
(
&
device
->
lock
);
return
S_FALSE
;
}
stopped
=
device
->
stopped
;
info
.
handle
=
0
;
info
.
req_device
=
WAVE_MAPPER
;
info
.
format
=
device
->
orig_fmt
;
info
.
callback
=
device
->
cb_info
.
callback
;
info
.
cb_user
=
device
->
cb_info
.
user
;
/* We have to use direct here so that we don't suddenly introduce ACM
* into a playing stream that hasn't been Prepared for it */
info
.
flags
=
(
device
->
cb_info
.
flags
<<
16
)
|
WAVE_FORMAT_DIRECT_QUERY
;
info
.
reset
=
FALSE
;
if
(
is_out
)
mr
=
WOD_Open
(
&
info
);
else
mr
=
WID_Open
(
&
info
);
if
(
mr
!=
MMSYSERR_NOERROR
){
TRACE
(
"New default device doesn't support this stream: %p
\n
"
,
device
->
handle
);
LeaveCriticalSection
(
&
device
->
lock
);
return
S_FALSE
;
}
hr
=
IAudioClient_Stop
(
device
->
client
);
if
(
FAILED
(
hr
))
WARN
(
"Stop failed: %08x
\n
"
,
hr
);
hr
=
IAudioClock_GetFrequency
(
device
->
clock
,
&
clock_freq
);
if
(
FAILED
(
hr
)){
WARN
(
"GetFrequency failed: %08x
\n
"
,
hr
);
return
hr
;
}
hr
=
IAudioClock_GetPosition
(
device
->
clock
,
&
clock_pos
,
NULL
);
if
(
FAILED
(
hr
)){
WARN
(
"GetPosition failed: %08x
\n
"
,
hr
);
return
hr
;
}
device
->
remainder_frames
=
MulDiv
(
clock_pos
,
device
->
samples_per_sec
,
clock_freq
)
-
device
->
last_clock_pos
;
info
.
handle
=
device
->
handle
;
info
.
flags
=
(
device
->
cb_info
.
flags
<<
16
)
|
WAVE_FORMAT_DIRECT
;
if
(
is_out
){
WOD_Close
((
HWAVEOUT
)
device
->
handle
);
device
->
parent
=
read_map
(
g_out_map
,
0
);
mr
=
WOD_Open
(
&
info
);
}
else
{
WID_Close
((
HWAVEIN
)
device
->
handle
);
device
->
parent
=
read_map
(
g_in_map
,
0
);
mr
=
WID_Open
(
&
info
);
}
if
(
mr
!=
MMSYSERR_NOERROR
){
ERR
(
"Opening new default device failed! %u
\n
"
,
mr
);
LeaveCriticalSection
(
&
device
->
lock
);
return
E_FAIL
;
}
HeapFree
(
GetProcessHeap
(),
0
,
info
.
format
);
if
(
!
stopped
)
WINMM_BeginPlaying
(
device
);
LeaveCriticalSection
(
&
device
->
lock
);
return
S_OK
;
}
static
HRESULT
WINAPI
notif_OnDefaultDeviceChanged
(
IMMNotificationClient
*
iface
,
EDataFlow
flow
,
ERole
role
,
const
WCHAR
*
device_id
)
{
UINT
i
;
TRACE
(
"%u %u %s
\n
"
,
flow
,
role
,
wine_dbgstr_w
(
device_id
));
if
(
role
!=
eConsole
)
return
S_OK
;
EnterCriticalSection
(
&
g_devthread_lock
);
if
(
flow
==
eRender
)
update_mapping
(
&
g_out_map
,
g_outmmdevices_count
,
device_id
);
else
update_mapping
(
&
g_in_map
,
g_inmmdevices_count
,
device_id
);
for
(
i
=
0
;
i
<
MAX_DEVICES
&&
g_out_mapper_devices
[
i
];
++
i
)
reroute_mapper_device
(
g_out_mapper_devices
[
i
],
TRUE
);
for
(
i
=
0
;
i
<
MAX_DEVICES
&&
g_in_mapper_devices
[
i
];
++
i
)
reroute_mapper_device
(
g_in_mapper_devices
[
i
],
FALSE
);
LeaveCriticalSection
(
&
g_devthread_lock
);
LeaveCriticalSection
(
&
g_devthread_lock
);
return
S_OK
;
return
S_OK
;
...
@@ -849,118 +948,119 @@ static MMRESULT WINMM_TryDeviceMapping(WINMM_Device *device, WAVEFORMATEX *fmt,
...
@@ -849,118 +948,119 @@ static MMRESULT WINMM_TryDeviceMapping(WINMM_Device *device, WAVEFORMATEX *fmt,
return
MMSYSERR_NOERROR
;
return
MMSYSERR_NOERROR
;
}
}
static
MMRESULT
WINMM_MapDevice
(
WINMM_Device
*
device
,
WAVEFORMATEX
*
fmt
,
static
MMRESULT
WINMM_MapDevice
(
WINMM_Device
*
device
,
BOOL
is_out
)
BOOL
is_out
)
{
{
MMRESULT
mr
;
MMRESULT
mr
;
WAVEFORMATEXTENSIBLE
*
fmtex
=
(
WAVEFORMATEXTENSIBLE
*
)
fmt
;
WAVEFORMATEXTENSIBLE
*
fmtex
=
(
WAVEFORMATEXTENSIBLE
*
)
device
->
orig_
fmt
;
TRACE
(
"(%p, %
p, %u)
\n
"
,
device
,
fmt
,
is_out
);
TRACE
(
"(%p, %
u)
\n
"
,
device
,
is_out
);
/* set up the ACM stream */
/* set up the ACM stream */
if
(
fmt
->
wFormatTag
!=
WAVE_FORMAT_PCM
&&
if
(
device
->
orig_
fmt
->
wFormatTag
!=
WAVE_FORMAT_PCM
&&
!
(
fmt
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
&&
!
(
device
->
orig_
fmt
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
&&
IsEqualGUID
(
&
fmtex
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_PCM
))){
IsEqualGUID
(
&
fmtex
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_PCM
))){
/* convert to PCM format if it's not already */
/* convert to PCM format if it's not already */
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
fmt
->
nChannels
,
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_fmt
,
fmt
->
nSamplesPerSec
,
16
,
is_out
);
device
->
orig_fmt
->
nChannels
,
device
->
orig_fmt
->
nSamplesPerSec
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
fmt
->
nChannels
,
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_fmt
,
fmt
->
nSamplesPerSec
,
8
,
is_out
);
device
->
orig_fmt
->
nChannels
,
device
->
orig_fmt
->
nSamplesPerSec
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
}
else
{
}
else
{
WORD
channels
;
WORD
channels
;
/* first try just changing bit depth and channels */
/* first try just changing bit depth and channels */
channels
=
fmt
->
nChannels
;
channels
=
device
->
orig_
fmt
->
nChannels
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
fmt
->
nSamplesPerSec
,
16
,
is_out
);
device
->
orig_
fmt
->
nSamplesPerSec
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
fmt
->
nSamplesPerSec
,
8
,
is_out
);
device
->
orig_
fmt
->
nSamplesPerSec
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
channels
=
(
channels
==
2
)
?
1
:
2
;
channels
=
(
channels
==
2
)
?
1
:
2
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
fmt
->
nSamplesPerSec
,
16
,
is_out
);
device
->
orig_
fmt
->
nSamplesPerSec
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
fmt
->
nSamplesPerSec
,
8
,
is_out
);
device
->
orig_
fmt
->
nSamplesPerSec
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
/* that didn't work, so now try different sample rates */
/* that didn't work, so now try different sample rates */
channels
=
fmt
->
nChannels
;
channels
=
device
->
orig_
fmt
->
nChannels
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
96000
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
96000
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
48000
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
48000
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
44100
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
44100
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
22050
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
22050
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
11025
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
11025
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
channels
=
(
channels
==
2
)
?
1
:
2
;
channels
=
(
channels
==
2
)
?
1
:
2
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
96000
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
96000
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
48000
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
48000
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
44100
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
44100
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
22050
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
22050
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
11025
,
16
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
11025
,
16
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
channels
=
fmt
->
nChannels
;
channels
=
device
->
orig_
fmt
->
nChannels
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
96000
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
96000
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
48000
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
48000
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
44100
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
44100
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
22050
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
22050
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
11025
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
11025
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
channels
=
(
channels
==
2
)
?
1
:
2
;
channels
=
(
channels
==
2
)
?
1
:
2
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
96000
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
96000
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
48000
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
48000
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
44100
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
44100
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
22050
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
22050
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
mr
=
WINMM_TryDeviceMapping
(
device
,
fmt
,
channels
,
11025
,
8
,
is_out
);
mr
=
WINMM_TryDeviceMapping
(
device
,
device
->
orig_
fmt
,
channels
,
11025
,
8
,
is_out
);
if
(
mr
==
MMSYSERR_NOERROR
)
if
(
mr
==
MMSYSERR_NOERROR
)
return
mr
;
return
mr
;
}
}
...
@@ -972,7 +1072,6 @@ static MMRESULT WINMM_MapDevice(WINMM_Device *device, WAVEFORMATEX *fmt,
...
@@ -972,7 +1072,6 @@ static MMRESULT WINMM_MapDevice(WINMM_Device *device, WAVEFORMATEX *fmt,
static
LRESULT
WINMM_OpenDevice
(
WINMM_Device
*
device
,
WINMM_OpenInfo
*
info
,
static
LRESULT
WINMM_OpenDevice
(
WINMM_Device
*
device
,
WINMM_OpenInfo
*
info
,
BOOL
is_out
)
BOOL
is_out
)
{
{
WAVEFORMATEX
fmt
,
*
passed_fmt
;
LRESULT
ret
=
MMSYSERR_NOMEM
;
LRESULT
ret
=
MMSYSERR_NOMEM
;
HRESULT
hr
;
HRESULT
hr
;
...
@@ -1000,30 +1099,34 @@ static LRESULT WINMM_OpenDevice(WINMM_Device *device, WINMM_OpenInfo *info,
...
@@ -1000,30 +1099,34 @@ static LRESULT WINMM_OpenDevice(WINMM_Device *device, WINMM_OpenInfo *info,
if
(
info
->
format
->
wFormatTag
==
WAVE_FORMAT_PCM
){
if
(
info
->
format
->
wFormatTag
==
WAVE_FORMAT_PCM
){
/* we aren't guaranteed that the struct in lpFormat is a full
/* we aren't guaranteed that the struct in lpFormat is a full
* WAVEFORMATEX struct, which IAC::IsFormatSupported requires */
* WAVEFORMATEX struct, which IAC::IsFormatSupported requires */
passed_fmt
=
&
fmt
;
device
->
orig_fmt
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WAVEFORMATEX
))
;
memcpy
(
passed
_fmt
,
info
->
format
,
sizeof
(
PCMWAVEFORMAT
));
memcpy
(
device
->
orig
_fmt
,
info
->
format
,
sizeof
(
PCMWAVEFORMAT
));
passed
_fmt
->
cbSize
=
0
;
device
->
orig
_fmt
->
cbSize
=
0
;
if
(
fmt
.
wBitsPerSample
%
8
!=
0
){
if
(
device
->
orig_fmt
->
wBitsPerSample
%
8
!=
0
){
WARN
(
"Fixing bad wBitsPerSample (%u)
\n
"
,
fmt
.
wBitsPerSample
);
WARN
(
"Fixing bad wBitsPerSample (%u)
\n
"
,
device
->
orig_fmt
->
wBitsPerSample
);
fmt
.
wBitsPerSample
=
(
fmt
.
wBitsPerSample
+
7
)
&
~
7
;
device
->
orig_fmt
->
wBitsPerSample
=
(
device
->
orig_fmt
->
wBitsPerSample
+
7
)
&
~
7
;
}
}
/* winmm ignores broken blockalign and avgbytes */
/* winmm ignores broken blockalign and avgbytes */
if
(
fmt
.
nBlockAlign
!=
fmt
.
nChannels
*
fmt
.
wBitsPerSample
/
8
){
if
(
device
->
orig_fmt
->
nBlockAlign
!=
device
->
orig_fmt
->
nChannels
*
device
->
orig_fmt
->
wBitsPerSample
/
8
){
WARN
(
"Fixing bad nBlockAlign (%u)
\n
"
,
fmt
.
nBlockAlign
);
WARN
(
"Fixing bad nBlockAlign (%u)
\n
"
,
device
->
orig_fmt
->
nBlockAlign
);
fmt
.
nBlockAlign
=
fmt
.
nChannels
*
fmt
.
wBitsPerSample
/
8
;
device
->
orig_fmt
->
nBlockAlign
=
device
->
orig_fmt
->
nChannels
*
device
->
orig_fmt
->
wBitsPerSample
/
8
;
}
}
if
(
fmt
.
nAvgBytesPerSec
!=
fmt
.
nSamplesPerSec
*
fmt
.
nBlockAlign
)
{
if
(
device
->
orig_fmt
->
nAvgBytesPerSec
!=
device
->
orig_fmt
->
nSamplesPerSec
*
device
->
orig_fmt
->
nBlockAlign
)
{
WARN
(
"Fixing bad nAvgBytesPerSec (%u)
\n
"
,
fmt
.
nAvgBytesPerSec
);
WARN
(
"Fixing bad nAvgBytesPerSec (%u)
\n
"
,
device
->
orig_fmt
->
nAvgBytesPerSec
);
fmt
.
nAvgBytesPerSec
=
fmt
.
nSamplesPerSec
*
fmt
.
nBlockAlign
;
device
->
orig_fmt
->
nAvgBytesPerSec
=
device
->
orig_fmt
->
nSamplesPerSec
*
device
->
orig_fmt
->
nBlockAlign
;
}
}
}
else
}
else
{
passed_fmt
=
info
->
format
;
device
->
orig_fmt
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WAVEFORMATEX
)
+
info
->
format
->
cbSize
);
memcpy
(
device
->
orig_fmt
,
info
->
format
,
sizeof
(
WAVEFORMATEX
)
+
info
->
format
->
cbSize
);
}
if
(
info
->
flags
&
WAVE_FORMAT_QUERY
){
if
(
info
->
flags
&
WAVE_FORMAT_QUERY
){
WAVEFORMATEX
*
closer_fmt
=
NULL
;
WAVEFORMATEX
*
closer_fmt
=
NULL
;
hr
=
IAudioClient_IsFormatSupported
(
device
->
client
,
hr
=
IAudioClient_IsFormatSupported
(
device
->
client
,
AUDCLNT_SHAREMODE_SHARED
,
passed
_fmt
,
&
closer_fmt
);
AUDCLNT_SHAREMODE_SHARED
,
device
->
orig
_fmt
,
&
closer_fmt
);
if
(
closer_fmt
)
if
(
closer_fmt
)
CoTaskMemFree
(
closer_fmt
);
CoTaskMemFree
(
closer_fmt
);
ret
=
hr
==
S_FALSE
?
WAVERR_BADFORMAT
:
hr2mmr
(
hr
);
ret
=
hr
==
S_FALSE
?
WAVERR_BADFORMAT
:
hr2mmr
(
hr
);
...
@@ -1032,10 +1135,10 @@ static LRESULT WINMM_OpenDevice(WINMM_Device *device, WINMM_OpenInfo *info,
...
@@ -1032,10 +1135,10 @@ static LRESULT WINMM_OpenDevice(WINMM_Device *device, WINMM_OpenInfo *info,
hr
=
IAudioClient_Initialize
(
device
->
client
,
AUDCLNT_SHAREMODE_SHARED
,
hr
=
IAudioClient_Initialize
(
device
->
client
,
AUDCLNT_SHAREMODE_SHARED
,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK
|
AUDCLNT_STREAMFLAGS_NOPERSIST
,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK
|
AUDCLNT_STREAMFLAGS_NOPERSIST
,
AC_BUFLEN
,
0
,
passed
_fmt
,
&
device
->
parent
->
session
);
AC_BUFLEN
,
0
,
device
->
orig
_fmt
,
&
device
->
parent
->
session
);
if
(
FAILED
(
hr
)){
if
(
FAILED
(
hr
)){
if
(
hr
==
AUDCLNT_E_UNSUPPORTED_FORMAT
){
if
(
hr
==
AUDCLNT_E_UNSUPPORTED_FORMAT
){
ret
=
WINMM_MapDevice
(
device
,
passed_fmt
,
is_out
);
ret
=
WINMM_MapDevice
(
device
,
is_out
);
if
(
ret
!=
MMSYSERR_NOERROR
||
info
->
flags
&
WAVE_FORMAT_QUERY
)
if
(
ret
!=
MMSYSERR_NOERROR
||
info
->
flags
&
WAVE_FORMAT_QUERY
)
goto
error
;
goto
error
;
}
else
{
}
else
{
...
@@ -1044,8 +1147,8 @@ static LRESULT WINMM_OpenDevice(WINMM_Device *device, WINMM_OpenInfo *info,
...
@@ -1044,8 +1147,8 @@ static LRESULT WINMM_OpenDevice(WINMM_Device *device, WINMM_OpenInfo *info,
goto
error
;
goto
error
;
}
}
}
else
{
}
else
{
device
->
bytes_per_frame
=
passed
_fmt
->
nBlockAlign
;
device
->
bytes_per_frame
=
device
->
orig
_fmt
->
nBlockAlign
;
device
->
samples_per_sec
=
passed
_fmt
->
nSamplesPerSec
;
device
->
samples_per_sec
=
device
->
orig
_fmt
->
nSamplesPerSec
;
}
}
hr
=
IAudioClient_GetService
(
device
->
client
,
&
IID_IAudioClock
,
hr
=
IAudioClient_GetService
(
device
->
client
,
&
IID_IAudioClock
,
...
@@ -1085,12 +1188,15 @@ static LRESULT WINMM_OpenDevice(WINMM_Device *device, WINMM_OpenInfo *info,
...
@@ -1085,12 +1188,15 @@ static LRESULT WINMM_OpenDevice(WINMM_Device *device, WINMM_OpenInfo *info,
goto
error
;
goto
error
;
}
}
device
->
played_frames
=
0
;
if
(
info
->
reset
){
device
->
last_clock_pos
=
0
;
device
->
played_frames
=
0
;
device
->
ofs_bytes
=
0
;
device
->
ofs_bytes
=
0
;
device
->
loop_counter
=
0
;
device
->
loop_counter
=
0
;
device
->
first
=
device
->
last
=
device
->
playing
=
device
->
loop_start
=
NULL
;
}
device
->
stopped
=
TRUE
;
device
->
stopped
=
TRUE
;
device
->
first
=
device
->
last
=
device
->
playing
=
device
->
loop_start
=
NULL
;
device
->
last_clock_pos
=
0
;
device
->
cb_info
.
flags
=
HIWORD
(
info
->
flags
&
CALLBACK_TYPEMASK
);
device
->
cb_info
.
flags
=
HIWORD
(
info
->
flags
&
CALLBACK_TYPEMASK
);
device
->
cb_info
.
callback
=
info
->
callback
;
device
->
cb_info
.
callback
=
info
->
callback
;
...
@@ -1116,42 +1222,57 @@ error:
...
@@ -1116,42 +1222,57 @@ error:
static
LRESULT
WOD_Open
(
WINMM_OpenInfo
*
info
)
static
LRESULT
WOD_Open
(
WINMM_OpenInfo
*
info
)
{
{
WINMM_Device
*
device
,
**
devices
;
WINMM_Device
*
device
;
WINMM_MMDevice
*
mmdevice
;
CRITICAL_SECTION
*
lock
;
UINT
internal_index
;
LRESULT
ret
=
MMSYSERR_ERROR
;
LRESULT
ret
=
MMSYSERR_ERROR
;
HRESULT
hr
;
HRESULT
hr
;
if
(
WINMM_IsMapper
(
info
->
req_device
)){
if
(
info
->
handle
!=
0
){
devices
=
g_out_mapper_devices
;
device
=
WINMM_GetDeviceFromHWAVE
(
info
->
handle
);
mmdevice
=
read_map
(
g_out_map
,
0
);
if
(
!
device
){
lock
=
&
g_devthread_lock
;
WARN
(
"Unexpected! Invalid info->handle given: %p
\n
"
,
info
->
handle
);
internal_index
=
MAPPER_INDEX
;
return
MMSYSERR_ERROR
;
}
EnterCriticalSection
(
&
device
->
lock
);
device
->
open
=
TRUE
;
}
else
{
}
else
{
if
(
info
->
req_device
>=
g_outmmdevices_count
)
CRITICAL_SECTION
*
lock
;
return
MMSYSERR_BADDEVICEID
;
UINT
internal_index
;
WINMM_Device
**
devices
;
WINMM_MMDevice
*
mmdevice
;
if
(
WINMM_IsMapper
(
info
->
req_device
)){
devices
=
g_out_mapper_devices
;
mmdevice
=
read_map
(
g_out_map
,
0
);
lock
=
&
g_devthread_lock
;
internal_index
=
MAPPER_INDEX
;
}
else
{
if
(
info
->
req_device
>=
g_outmmdevices_count
)
return
MMSYSERR_BADDEVICEID
;
mmdevice
=
read_map
(
g_out_map
,
info
->
req_device
);
mmdevice
=
read_map
(
g_out_map
,
info
->
req_device
);
if
(
!
mmdevice
->
out_caps
.
szPname
[
0
])
if
(
!
mmdevice
->
out_caps
.
szPname
[
0
])
return
MMSYSERR_NOTENABLED
;
return
MMSYSERR_NOTENABLED
;
devices
=
mmdevice
->
devices
;
devices
=
mmdevice
->
devices
;
lock
=
&
mmdevice
->
lock
;
lock
=
&
mmdevice
->
lock
;
internal_index
=
mmdevice
->
index
;
internal_index
=
mmdevice
->
index
;
}
}
EnterCriticalSection
(
lock
);
EnterCriticalSection
(
lock
);
device
=
WINMM_FindUnusedDevice
(
devices
,
mmdevice
,
internal_index
,
TRUE
);
if
(
!
device
){
LeaveCriticalSection
(
lock
);
return
MMSYSERR_ALLOCATED
;
}
device
=
WINMM_FindUnusedDevice
(
devices
,
mmdevice
,
internal_index
,
TRUE
);
if
(
!
device
){
LeaveCriticalSection
(
lock
);
LeaveCriticalSection
(
lock
);
return
MMSYSERR_ALLOCATED
;
}
}
LeaveCriticalSection
(
lock
);
ret
=
WINMM_OpenDevice
(
device
,
info
,
TRUE
);
ret
=
WINMM_OpenDevice
(
device
,
info
,
TRUE
);
if
((
info
->
flags
&
WAVE_FORMAT_QUERY
)
||
ret
!=
MMSYSERR_NOERROR
)
if
((
info
->
flags
&
WAVE_FORMAT_QUERY
)
||
ret
!=
MMSYSERR_NOERROR
)
goto
error
;
goto
error
;
...
@@ -1463,10 +1584,11 @@ static WAVEHDR *WOD_MarkDoneHeaders(WINMM_Device *device)
...
@@ -1463,10 +1584,11 @@ static WAVEHDR *WOD_MarkDoneHeaders(WINMM_Device *device)
nloops
=
device
->
loop_counter
;
nloops
=
device
->
loop_counter
;
while
(
queue
&&
while
(
queue
&&
(
queue_frames
+=
WINMM_HeaderLenFrames
(
device
,
queue
))
<=
(
queue_frames
+=
WINMM_HeaderLenFrames
(
device
,
queue
))
<=
clock_frames
-
device
->
last_clock_pos
){
clock_frames
-
device
->
last_clock_pos
+
device
->
remainder_frames
){
if
(
!
nloops
){
if
(
!
nloops
){
last
=
queue
;
last
=
queue
;
device
->
last_clock_pos
+=
queue_frames
;
device
->
last_clock_pos
+=
queue_frames
;
device
->
remainder_frames
=
0
;
queue_frames
=
0
;
queue_frames
=
0
;
queue
=
device
->
first
=
queue
->
lpNext
;
queue
=
device
->
first
=
queue
->
lpNext
;
}
else
{
}
else
{
...
@@ -1617,7 +1739,10 @@ static void WOD_PushData(WINMM_Device *device)
...
@@ -1617,7 +1739,10 @@ static void WOD_PushData(WINMM_Device *device)
goto
exit
;
goto
exit
;
}
}
device
->
played_frames
+=
avail_frames
;
if
(
device
->
orig_fmt
->
nSamplesPerSec
!=
device
->
samples_per_sec
)
device
->
played_frames
+=
MulDiv
(
avail_frames
,
device
->
orig_fmt
->
nSamplesPerSec
,
device
->
samples_per_sec
);
else
device
->
played_frames
+=
avail_frames
;
exit:
exit:
cb_info
=
device
->
cb_info
;
cb_info
=
device
->
cb_info
;
...
@@ -1946,8 +2071,8 @@ static LRESULT WINMM_GetPosition(HWAVE hwave, MMTIME *time)
...
@@ -1946,8 +2071,8 @@ static LRESULT WINMM_GetPosition(HWAVE hwave, MMTIME *time)
return
MMSYSERR_INVALHANDLE
;
return
MMSYSERR_INVALHANDLE
;
played_frames
=
device
->
played_frames
;
played_frames
=
device
->
played_frames
;
sample_rate
=
device
->
samples_per_s
ec
;
sample_rate
=
device
->
orig_fmt
->
nSamplesPerS
ec
;
bytes_per_frame
=
device
->
bytes_per_frame
;
bytes_per_frame
=
device
->
orig_fmt
->
nBlockAlign
;
LeaveCriticalSection
(
&
device
->
lock
);
LeaveCriticalSection
(
&
device
->
lock
);
...
@@ -2591,11 +2716,13 @@ MMRESULT WINAPI waveOutOpen(LPHWAVEOUT lphWaveOut, UINT uDeviceID,
...
@@ -2591,11 +2716,13 @@ MMRESULT WINAPI waveOutOpen(LPHWAVEOUT lphWaveOut, UINT uDeviceID,
if
(
res
!=
MMSYSERR_NOERROR
)
if
(
res
!=
MMSYSERR_NOERROR
)
return
res
;
return
res
;
info
.
handle
=
0
;
info
.
format
=
(
WAVEFORMATEX
*
)
lpFormat
;
info
.
format
=
(
WAVEFORMATEX
*
)
lpFormat
;
info
.
callback
=
dwCallback
;
info
.
callback
=
dwCallback
;
info
.
cb_user
=
dwInstance
;
info
.
cb_user
=
dwInstance
;
info
.
req_device
=
uDeviceID
;
info
.
req_device
=
uDeviceID
;
info
.
flags
=
dwFlags
;
info
.
flags
=
dwFlags
;
info
.
reset
=
TRUE
;
res
=
SendMessageW
(
g_devices_hwnd
,
WODM_OPEN
,
(
DWORD_PTR
)
&
info
,
0
);
res
=
SendMessageW
(
g_devices_hwnd
,
WODM_OPEN
,
(
DWORD_PTR
)
&
info
,
0
);
if
(
res
!=
MMSYSERR_NOERROR
)
if
(
res
!=
MMSYSERR_NOERROR
)
...
@@ -3219,11 +3346,13 @@ MMRESULT WINAPI waveInOpen(HWAVEIN* lphWaveIn, UINT uDeviceID,
...
@@ -3219,11 +3346,13 @@ MMRESULT WINAPI waveInOpen(HWAVEIN* lphWaveIn, UINT uDeviceID,
if
(
res
!=
MMSYSERR_NOERROR
)
if
(
res
!=
MMSYSERR_NOERROR
)
return
res
;
return
res
;
info
.
handle
=
0
;
info
.
format
=
(
WAVEFORMATEX
*
)
lpFormat
;
info
.
format
=
(
WAVEFORMATEX
*
)
lpFormat
;
info
.
callback
=
dwCallback
;
info
.
callback
=
dwCallback
;
info
.
cb_user
=
dwInstance
;
info
.
cb_user
=
dwInstance
;
info
.
req_device
=
uDeviceID
;
info
.
req_device
=
uDeviceID
;
info
.
flags
=
dwFlags
;
info
.
flags
=
dwFlags
;
info
.
reset
=
TRUE
;
res
=
SendMessageW
(
g_devices_hwnd
,
WIDM_OPEN
,
(
DWORD_PTR
)
&
info
,
0
);
res
=
SendMessageW
(
g_devices_hwnd
,
WIDM_OPEN
,
(
DWORD_PTR
)
&
info
,
0
);
if
(
res
!=
MMSYSERR_NOERROR
)
if
(
res
!=
MMSYSERR_NOERROR
)
...
...
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