Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
f5baa375
Commit
f5baa375
authored
May 23, 2023
by
Davide Beatrici
Committed by
Alexandre Julliard
May 23, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winepulse: Implement is_format_supported in unixlib.
parent
2127a8a0
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
186 additions
and
159 deletions
+186
-159
mmdevdrv.c
dlls/winepulse.drv/mmdevdrv.c
+17
-157
pulse.c
dlls/winepulse.drv/pulse.c
+169
-2
No files found.
dlls/winepulse.drv/mmdevdrv.c
View file @
f5baa375
...
...
@@ -620,27 +620,6 @@ static void dump_fmt(const WAVEFORMATEX *fmt)
}
}
static
WAVEFORMATEX
*
clone_format
(
const
WAVEFORMATEX
*
fmt
)
{
WAVEFORMATEX
*
ret
;
size_t
size
;
if
(
fmt
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
)
size
=
sizeof
(
WAVEFORMATEXTENSIBLE
);
else
size
=
sizeof
(
WAVEFORMATEX
);
ret
=
CoTaskMemAlloc
(
size
);
if
(
!
ret
)
return
NULL
;
memcpy
(
ret
,
fmt
,
size
);
ret
->
cbSize
=
size
-
sizeof
(
WAVEFORMATEX
);
return
ret
;
}
static
void
session_init_vols
(
AudioSession
*
session
,
UINT
channels
)
{
if
(
session
->
channel_count
<
channels
)
{
...
...
@@ -888,152 +867,33 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface,
WAVEFORMATEX
**
out
)
{
ACImpl
*
This
=
impl_from_IAudioClient3
(
iface
);
HRESULT
hr
=
S_OK
;
WAVEFORMATEX
*
closest
=
NULL
;
BOOL
exclusive
;
struct
is_format_supported_params
params
;
TRACE
(
"(%p)->(%x, %p, %p)
\n
"
,
This
,
mode
,
fmt
,
out
);
if
(
!
fmt
)
return
E_POINTER
;
if
(
out
)
*
out
=
NULL
;
if
(
mode
==
AUDCLNT_SHAREMODE_EXCLUSIVE
)
{
exclusive
=
1
;
out
=
NULL
;
}
else
if
(
mode
==
AUDCLNT_SHAREMODE_SHARED
)
{
exclusive
=
0
;
if
(
!
out
)
return
E_POINTER
;
}
else
return
E_INVALIDARG
;
if
(
fmt
->
nChannels
==
0
)
return
AUDCLNT_E_UNSUPPORTED_FORMAT
;
closest
=
clone_format
(
fmt
);
if
(
!
closest
)
return
E_OUTOFMEMORY
;
dump_fmt
(
fmt
);
switch
(
fmt
->
wFormatTag
)
{
case
WAVE_FORMAT_EXTENSIBLE
:
{
WAVEFORMATEXTENSIBLE
*
ext
=
(
WAVEFORMATEXTENSIBLE
*
)
closest
;
if
((
fmt
->
cbSize
!=
sizeof
(
WAVEFORMATEXTENSIBLE
)
-
sizeof
(
WAVEFORMATEX
)
&&
fmt
->
cbSize
!=
sizeof
(
WAVEFORMATEXTENSIBLE
))
||
fmt
->
nBlockAlign
!=
fmt
->
wBitsPerSample
/
8
*
fmt
->
nChannels
||
ext
->
Samples
.
wValidBitsPerSample
>
fmt
->
wBitsPerSample
||
fmt
->
nAvgBytesPerSec
!=
fmt
->
nBlockAlign
*
fmt
->
nSamplesPerSec
)
{
hr
=
E_INVALIDARG
;
break
;
}
if
(
exclusive
)
{
UINT32
mask
=
0
,
i
,
channels
=
0
;
if
(
!
(
ext
->
dwChannelMask
&
(
SPEAKER_ALL
|
SPEAKER_RESERVED
)))
{
for
(
i
=
1
;
!
(
i
&
SPEAKER_RESERVED
);
i
<<=
1
)
{
if
(
i
&
ext
->
dwChannelMask
)
{
mask
|=
i
;
channels
++
;
}
}
if
(
channels
!=
fmt
->
nChannels
||
(
ext
->
dwChannelMask
&
~
mask
))
{
hr
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
}
else
{
hr
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
}
if
(
IsEqualGUID
(
&
ext
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
{
if
(
fmt
->
wBitsPerSample
!=
32
)
{
hr
=
E_INVALIDARG
;
break
;
}
if
(
fmt
)
dump_fmt
(
fmt
);
if
(
ext
->
Samples
.
wValidBitsPerSample
!=
fmt
->
wBitsPerSample
)
{
hr
=
S_FALSE
;
ext
->
Samples
.
wValidBitsPerSample
=
fmt
->
wBitsPerSample
;
}
}
else
if
(
IsEqualGUID
(
&
ext
->
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_PCM
))
{
if
(
!
fmt
->
wBitsPerSample
||
fmt
->
wBitsPerSample
>
32
||
fmt
->
wBitsPerSample
%
8
)
{
hr
=
E_INVALIDARG
;
break
;
}
params
.
device
=
This
->
device_name
;
params
.
flow
=
This
->
dataflow
;
params
.
share
=
mode
;
params
.
fmt_in
=
fmt
;
params
.
fmt_out
=
NULL
;
if
(
ext
->
Samples
.
wValidBitsPerSample
!=
fmt
->
wBitsPerSample
&&
!
(
fmt
->
wBitsPerSample
==
32
&&
ext
->
Samples
.
wValidBitsPerSample
==
24
))
{
hr
=
S_FALSE
;
ext
->
Samples
.
wValidBitsPerSample
=
fmt
->
wBitsPerSample
;
break
;
}
}
else
{
hr
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
break
;
if
(
out
)
{
*
out
=
NULL
;
if
(
mode
==
AUDCLNT_SHAREMODE_SHARED
)
params
.
fmt_out
=
CoTaskMemAlloc
(
sizeof
(
*
params
.
fmt_out
));
}
case
WAVE_FORMAT_ALAW
:
case
WAVE_FORMAT_MULAW
:
if
(
fmt
->
wBitsPerSample
!=
8
)
{
hr
=
E_INVALIDARG
;
break
;
}
/* Fall-through */
case
WAVE_FORMAT_IEEE_FLOAT
:
if
(
fmt
->
wFormatTag
==
WAVE_FORMAT_IEEE_FLOAT
&&
fmt
->
wBitsPerSample
!=
32
)
{
hr
=
E_INVALIDARG
;
break
;
}
/* Fall-through */
case
WAVE_FORMAT_PCM
:
if
(
fmt
->
wFormatTag
==
WAVE_FORMAT_PCM
&&
(
!
fmt
->
wBitsPerSample
||
fmt
->
wBitsPerSample
>
32
||
fmt
->
wBitsPerSample
%
8
))
{
hr
=
E_INVALIDARG
;
break
;
}
if
(
fmt
->
nChannels
>
2
)
{
hr
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
/*
* fmt->cbSize, fmt->nBlockAlign and fmt->nAvgBytesPerSec seem to be
* ignored, invalid values are happily accepted.
*/
break
;
default:
hr
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
pulse_call
(
is_format_supported
,
&
params
);
if
(
exclusive
&&
hr
!=
S_OK
)
{
hr
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
CoTaskMemFree
(
closest
);
}
else
if
(
hr
!=
S_FALSE
)
CoTaskMemFree
(
closest
);
if
(
params
.
result
==
S_FALSE
)
*
out
=
&
params
.
fmt_out
->
Format
;
else
*
out
=
closest
;
CoTaskMemFree
(
params
.
fmt_out
)
;
/* Winepulse does not currently support exclusive mode, if you know of an
* application that uses it, I will correct this..
*/
if
(
hr
==
S_OK
&&
exclusive
)
return
This
->
dataflow
==
eCapture
?
AUDCLNT_E_UNSUPPORTED_FORMAT
:
AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED
;
TRACE
(
"returning: %08lx %p
\n
"
,
hr
,
out
?
*
out
:
NULL
);
return
hr
;
return
params
.
result
;
}
static
HRESULT
WINAPI
AudioClient_GetMixFormat
(
IAudioClient3
*
iface
,
...
...
dlls/winepulse.drv/pulse.c
View file @
f5baa375
...
...
@@ -2077,6 +2077,149 @@ static NTSTATUS pulse_release_capture_buffer(void *args)
return
STATUS_SUCCESS
;
}
static
NTSTATUS
pulse_is_format_supported
(
void
*
args
)
{
struct
is_format_supported_params
*
params
=
args
;
WAVEFORMATEXTENSIBLE
in
;
WAVEFORMATEXTENSIBLE
*
out
;
const
WAVEFORMATEX
*
fmt
=
&
in
.
Format
;
const
BOOLEAN
exclusive
=
params
->
share
==
AUDCLNT_SHAREMODE_EXCLUSIVE
;
params
->
result
=
S_OK
;
if
(
!
params
->
fmt_in
||
(
params
->
share
==
AUDCLNT_SHAREMODE_SHARED
&&
!
params
->
fmt_out
))
params
->
result
=
E_POINTER
;
else
if
(
params
->
share
!=
AUDCLNT_SHAREMODE_SHARED
&&
params
->
share
!=
AUDCLNT_SHAREMODE_EXCLUSIVE
)
params
->
result
=
E_INVALIDARG
;
else
{
memcpy
(
&
in
,
params
->
fmt_in
,
params
->
fmt_in
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
?
sizeof
(
in
)
:
sizeof
(
in
.
Format
));
if
(
fmt
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
)
{
if
(
fmt
->
cbSize
<
sizeof
(
WAVEFORMATEXTENSIBLE
)
-
sizeof
(
WAVEFORMATEX
))
params
->
result
=
E_INVALIDARG
;
else
if
(
fmt
->
nAvgBytesPerSec
==
0
||
fmt
->
nBlockAlign
==
0
||
(
in
.
Samples
.
wValidBitsPerSample
>
fmt
->
wBitsPerSample
))
params
->
result
=
E_INVALIDARG
;
else
if
(
fmt
->
nChannels
==
0
)
params
->
result
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
}
}
if
(
FAILED
(
params
->
result
))
return
STATUS_SUCCESS
;
if
(
exclusive
)
out
=
&
in
;
else
{
out
=
params
->
fmt_out
;
memcpy
(
out
,
fmt
,
fmt
->
wFormatTag
==
WAVE_FORMAT_EXTENSIBLE
?
sizeof
(
*
out
)
:
sizeof
((
*
out
).
Format
));
}
switch
(
fmt
->
wFormatTag
)
{
case
WAVE_FORMAT_EXTENSIBLE
:
{
if
((
fmt
->
cbSize
!=
sizeof
(
WAVEFORMATEXTENSIBLE
)
-
sizeof
(
WAVEFORMATEX
)
&&
fmt
->
cbSize
!=
sizeof
(
WAVEFORMATEXTENSIBLE
))
||
fmt
->
nBlockAlign
!=
fmt
->
wBitsPerSample
/
8
*
fmt
->
nChannels
||
in
.
Samples
.
wValidBitsPerSample
>
fmt
->
wBitsPerSample
||
fmt
->
nAvgBytesPerSec
!=
fmt
->
nBlockAlign
*
fmt
->
nSamplesPerSec
)
{
params
->
result
=
E_INVALIDARG
;
break
;
}
if
(
exclusive
)
{
UINT32
mask
=
0
,
i
,
channels
=
0
;
if
(
!
(
in
.
dwChannelMask
&
(
SPEAKER_ALL
|
SPEAKER_RESERVED
)))
{
for
(
i
=
1
;
!
(
i
&
SPEAKER_RESERVED
);
i
<<=
1
)
{
if
(
i
&
in
.
dwChannelMask
)
{
mask
|=
i
;
++
channels
;
}
}
if
(
channels
!=
fmt
->
nChannels
||
(
in
.
dwChannelMask
&
~
mask
))
{
params
->
result
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
}
else
{
params
->
result
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
}
if
(
IsEqualGUID
(
&
in
.
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
{
if
(
fmt
->
wBitsPerSample
!=
32
)
{
params
->
result
=
E_INVALIDARG
;
break
;
}
if
(
in
.
Samples
.
wValidBitsPerSample
!=
fmt
->
wBitsPerSample
)
{
params
->
result
=
S_FALSE
;
out
->
Samples
.
wValidBitsPerSample
=
fmt
->
wBitsPerSample
;
}
}
else
if
(
IsEqualGUID
(
&
in
.
SubFormat
,
&
KSDATAFORMAT_SUBTYPE_PCM
))
{
if
(
!
fmt
->
wBitsPerSample
||
fmt
->
wBitsPerSample
>
32
||
fmt
->
wBitsPerSample
%
8
)
{
params
->
result
=
E_INVALIDARG
;
break
;
}
if
(
in
.
Samples
.
wValidBitsPerSample
!=
fmt
->
wBitsPerSample
&&
!
(
fmt
->
wBitsPerSample
==
32
&&
in
.
Samples
.
wValidBitsPerSample
==
24
))
{
params
->
result
=
S_FALSE
;
out
->
Samples
.
wValidBitsPerSample
=
fmt
->
wBitsPerSample
;
break
;
}
}
else
{
params
->
result
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
break
;
}
case
WAVE_FORMAT_ALAW
:
case
WAVE_FORMAT_MULAW
:
if
(
fmt
->
wBitsPerSample
!=
8
)
{
params
->
result
=
E_INVALIDARG
;
break
;
}
/* Fall-through */
case
WAVE_FORMAT_IEEE_FLOAT
:
if
(
fmt
->
wFormatTag
==
WAVE_FORMAT_IEEE_FLOAT
&&
fmt
->
wBitsPerSample
!=
32
)
{
params
->
result
=
E_INVALIDARG
;
break
;
}
/* Fall-through */
case
WAVE_FORMAT_PCM
:
{
if
(
fmt
->
wFormatTag
==
WAVE_FORMAT_PCM
&&
(
!
fmt
->
wBitsPerSample
||
fmt
->
wBitsPerSample
>
32
||
fmt
->
wBitsPerSample
%
8
))
{
params
->
result
=
E_INVALIDARG
;
break
;
}
if
(
fmt
->
nChannels
>
2
)
{
params
->
result
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
/* fmt->cbSize, fmt->nBlockAlign and fmt->nAvgBytesPerSec seem to be
* ignored, invalid values are happily accepted. */
break
;
}
default:
params
->
result
=
AUDCLNT_E_UNSUPPORTED_FORMAT
;
break
;
}
/* This driver does not support exclusive mode. */
if
(
exclusive
&&
params
->
result
==
S_OK
)
params
->
result
=
params
->
flow
==
eCapture
?
AUDCLNT_E_UNSUPPORTED_FORMAT
:
AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED
;
return
STATUS_SUCCESS
;
}
static
NTSTATUS
pulse_get_mix_format
(
void
*
args
)
{
struct
get_mix_format_params
*
params
=
args
;
...
...
@@ -2395,7 +2538,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
pulse_release_render_buffer
,
pulse_get_capture_buffer
,
pulse_release_capture_buffer
,
pulse_
not_implemen
ted
,
pulse_
is_format_suppor
ted
,
pulse_get_mix_format
,
pulse_get_device_period
,
pulse_get_buffer_size
,
...
...
@@ -2561,6 +2704,30 @@ static NTSTATUS pulse_wow64_get_capture_buffer(void *args)
return
STATUS_SUCCESS
;
};
static
NTSTATUS
pulse_wow64_is_format_supported
(
void
*
args
)
{
struct
{
PTR32
device
;
EDataFlow
flow
;
AUDCLNT_SHAREMODE
share
;
PTR32
fmt_in
;
PTR32
fmt_out
;
HRESULT
result
;
}
*
params32
=
args
;
struct
is_format_supported_params
params
=
{
.
device
=
ULongToPtr
(
params32
->
device
),
.
flow
=
params32
->
flow
,
.
share
=
params32
->
share
,
.
fmt_in
=
ULongToPtr
(
params32
->
fmt_in
),
.
fmt_out
=
ULongToPtr
(
params32
->
fmt_out
)
};
pulse_is_format_supported
(
&
params
);
params32
->
result
=
params
.
result
;
return
STATUS_SUCCESS
;
}
static
NTSTATUS
pulse_wow64_get_mix_format
(
void
*
args
)
{
struct
...
...
@@ -2840,7 +3007,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
pulse_release_render_buffer
,
pulse_wow64_get_capture_buffer
,
pulse_release_capture_buffer
,
pulse_
not_implemen
ted
,
pulse_
wow64_is_format_suppor
ted
,
pulse_wow64_get_mix_format
,
pulse_wow64_get_device_period
,
pulse_wow64_get_buffer_size
,
...
...
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