[PATCH 0/5] MR10243: mmdevapi: Take the wave format validation code from the tests.
From: Giovanni Mascellani <gmascellani@codeweavers.com> --- dlls/winepulse.drv/pulse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 8033f0f851b..b0b92a7e1c7 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -962,6 +962,8 @@ static HRESULT pulse_spec_from_waveformat(struct pulse_stream *stream, const WAV stream->ss.format = PA_SAMPLE_U8; else if (fmt->wBitsPerSample == 16) stream->ss.format = PA_SAMPLE_S16LE; + else if (fmt->wBitsPerSample == 24) + stream->ss.format = PA_SAMPLE_S24LE; else if (fmt->wBitsPerSample == 32) stream->ss.format = PA_SAMPLE_S32LE; else -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10243
From: Giovanni Mascellani <gmascellani@codeweavers.com> --- dlls/winepulse.drv/pulse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index b0b92a7e1c7..953bc55ab81 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -974,7 +974,7 @@ static HRESULT pulse_spec_from_waveformat(struct pulse_stream *stream, const WAV WAVEFORMATEXTENSIBLE *wfe = (WAVEFORMATEXTENSIBLE*)fmt; UINT mask = wfe->dwChannelMask; unsigned i = 0, j; - if (fmt->cbSize != (sizeof(*wfe) - sizeof(*fmt)) && fmt->cbSize != sizeof(*wfe)) + if (fmt->cbSize < sizeof(*wfe) - sizeof(*fmt)) break; if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) && (!wfe->Samples.wValidBitsPerSample || wfe->Samples.wValidBitsPerSample == 32) && -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10243
From: Giovanni Mascellani <gmascellani@codeweavers.com> They're not supposed to be supported by mmdevapi in the first place. --- dlls/winepulse.drv/pulse.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 953bc55ab81..d7a9985bb39 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -1028,19 +1028,6 @@ static HRESULT pulse_spec_from_waveformat(struct pulse_stream *stream, const WAV } break; } - case WAVE_FORMAT_ALAW: - case WAVE_FORMAT_MULAW: - if (fmt->wBitsPerSample != 8) { - FIXME("Unsupported bpp %u for LAW\n", fmt->wBitsPerSample); - return AUDCLNT_E_UNSUPPORTED_FORMAT; - } - if (fmt->nChannels != 1 && fmt->nChannels != 2) { - FIXME("Unsupported channels %u for LAW\n", fmt->nChannels); - return AUDCLNT_E_UNSUPPORTED_FORMAT; - } - stream->ss.format = fmt->wFormatTag == WAVE_FORMAT_MULAW ? PA_SAMPLE_ULAW : PA_SAMPLE_ALAW; - pa_channel_map_init_auto(&stream->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA); - break; default: WARN("Unhandled tag %x\n", fmt->wFormatTag); return AUDCLNT_E_UNSUPPORTED_FORMAT; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10243
From: Giovanni Mascellani <gmascellani@codeweavers.com> Windows format with 24 valid bits out of 32 stores the valid bits as the most significant ones. In PulseAudio format PA_SAMPLE_S24_32LE stores the valid bits as the least significant ones, so the two formats are not compatible. It doesn't seem PulseAudio is able to express the Windows format (in principle we could just pretend samples are 32 bits and hope the least significant bits are inaudible, but since the code has been broken for years and nobody seems to have ever complained, probably nobody cares about 24-on-32 bit at all). --- dlls/winepulse.drv/pulse.c | 4 +--- dlls/winmm/tests/wave.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index d7a9985bb39..58087e553fa 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -1000,9 +1000,7 @@ static HRESULT pulse_spec_from_waveformat(struct pulse_stream *stream, const WAV stream->ss.format = PA_SAMPLE_S24LE; break; case 32: - if (valid == 24) - stream->ss.format = PA_SAMPLE_S24_32LE; - else if (valid == 32) + if (valid == 32) stream->ss.format = PA_SAMPLE_S32LE; break; default: diff --git a/dlls/winmm/tests/wave.c b/dlls/winmm/tests/wave.c index acf8599ce72..5e3a5341423 100644 --- a/dlls/winmm/tests/wave.c +++ b/dlls/winmm/tests/wave.c @@ -1872,6 +1872,8 @@ static void test_PlaySound(void) ok(br, "PlaySound failed, got %d\n", br); br = PlaySoundA("test_s24_32le.wav", GetModuleHandleA(NULL), SND_RESOURCE | SND_NODEFAULT); + /* Not supported on some Wine drivers. */ + todo_wine_if(!br) ok(br, "PlaySound failed, got %d\n", br); br = PlaySoundA("test_alaw.wav", GetModuleHandleA(NULL), SND_RESOURCE | SND_NODEFAULT); @@ -2086,7 +2088,9 @@ static void test_format(WAVEFORMATEXTENSIBLE *fmt) || fmt->Format.wFormatTag == WAVE_FORMAT_ALAW || fmt->Format.wFormatTag == WAVE_FORMAT_MULAW || fmt->Format.cbSize > sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) /* Native seems to largely ignore when the channel mask has nonsensical values, while Wine is more picky. */ - || (fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && __popcnt(fmt->dwChannelMask) != fmt->Format.nChannels))) + || (fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && __popcnt(fmt->dwChannelMask) != fmt->Format.nChannels) + /* Some drivers do not support 24-on-32 bits samples. */ + || (fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && fmt->Format.wBitsPerSample == 32 && fmt->Samples.wValidBitsPerSample == 24))) ok(mmr == expected || broken(channel_mismatch), "waveOutOpen(0) got result %#08x, expected %#08x\n", mmr, expected); ok((mmr == MMSYSERR_NOERROR) == !!hwo, "Unexpected waveout %p\n", hwo); @@ -2104,7 +2108,9 @@ static void test_format(WAVEFORMATEXTENSIBLE *fmt) || fmt->Format.cbSize > sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) /* Wine currently doesn't accept 24-bit PCM in direct mode. */ || fmt->Format.wBitsPerSample == 24 - || (fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && __popcnt(fmt->dwChannelMask) != fmt->Format.nChannels))) + || (fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && __popcnt(fmt->dwChannelMask) != fmt->Format.nChannels) + /* Some drivers do not support 24-on-32 bits samples. */ + || (fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && fmt->Format.wBitsPerSample == 32 && fmt->Samples.wValidBitsPerSample == 24))) ok(mmr == expected || (mmr == MMSYSERR_INVALPARAM && expected == WAVERR_BADFORMAT) || broken(channel_mismatch), "waveOutOpen(DIRECT) got result %#08x, expected %#08x\n", mmr, expected); ok((mmr == MMSYSERR_NOERROR) == !!hwo, "Unexpected waveout %p\n", hwo); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10243
From: Giovanni Mascellani <gmascellani@codeweavers.com> --- dlls/mmdevapi/client.c | 216 ++++++++++++++++------------------ dlls/mmdevapi/tests/capture.c | 48 ++++++-- dlls/mmdevapi/tests/render.c | 20 ++-- 3 files changed, 155 insertions(+), 129 deletions(-) diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index deab9cb0050..ef3e319fb89 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -359,122 +359,69 @@ skip: return wcsdup(name); } -static HRESULT validate_wfx(const WAVEFORMATEX *fmt, AUDCLNT_SHAREMODE share_mode) -{ - BOOL exclusive = (share_mode == AUDCLNT_SHAREMODE_EXCLUSIVE); - const WAVEFORMATEXTENSIBLE *fmtx = (const void *)fmt; - HRESULT ret = S_OK; +HRESULT validate_fmt(const WAVEFORMATEXTENSIBLE *fmt, BOOL compatible) +{ + WAVEFORMATEXTENSIBLE fmt2 = *fmt; + HRESULT ret; + + /* Reduce non-extensible formats to extensible ones. */ + if (fmt2.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) + { + switch (fmt2.Format.wFormatTag) + { + case WAVE_FORMAT_PCM: fmt2.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; break; + case WAVE_FORMAT_IEEE_FLOAT: fmt2.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; break; + default: return AUDCLNT_E_UNSUPPORTED_FORMAT; + } - if (share_mode != AUDCLNT_SHAREMODE_SHARED && share_mode != AUDCLNT_SHAREMODE_EXCLUSIVE) - return E_INVALIDARG; + if (fmt2.Format.nChannels > 2) + return E_INVALIDARG; - if (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE) { - if (fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) - ret = E_INVALIDARG; - else if (fmt->nAvgBytesPerSec == 0 || fmt->nBlockAlign == 0 || - (fmtx->Samples.wValidBitsPerSample > fmt->wBitsPerSample)) - ret = E_INVALIDARG; - else if (fmt->nChannels == 0) - ret = AUDCLNT_E_UNSUPPORTED_FORMAT; + fmt2.dwChannelMask = (1u << fmt2.Format.nChannels) - 1; + fmt2.Samples.wValidBitsPerSample = fmt2.Format.wBitsPerSample; + fmt2.Format.cbSize = sizeof(fmt2) - sizeof(fmt2.Format); } - if (FAILED(ret)) - return ret; - - if (fmt->nSamplesPerSec == 0 || fmt->nBlockAlign == 0) + if (fmt2.Format.cbSize < sizeof(fmt2) - sizeof(fmt2.Format)) ret = E_INVALIDARG; - - 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 || - fmtx->Samples.wValidBitsPerSample > fmt->wBitsPerSample || - fmt->nAvgBytesPerSec != fmt->nBlockAlign * fmt->nSamplesPerSec) { - ret = E_INVALIDARG; - } - - if (exclusive) { - UINT32 mask = 0, i, channels = 0; - - if (!(fmtx->dwChannelMask & (SPEAKER_ALL | SPEAKER_RESERVED))) { - for (i = 1; !(i & SPEAKER_RESERVED); i <<= 1) { - if (i & fmtx->dwChannelMask) { - mask |= i; - ++channels; - } - } - - if (channels != fmt->nChannels || (fmtx->dwChannelMask & ~mask)) { - ret = AUDCLNT_E_UNSUPPORTED_FORMAT; - break; - } - } else { - ret = AUDCLNT_E_UNSUPPORTED_FORMAT; - break; - } - } - - if (IsEqualGUID(&fmtx->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) { - if (fmt->wBitsPerSample != 32) { - ret = E_INVALIDARG; - break; - } - - if (fmtx->Samples.wValidBitsPerSample != fmt->wBitsPerSample) { - ret = S_FALSE; - } - } else if (IsEqualGUID(&fmtx->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) { - if (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8) { - ret = E_INVALIDARG; - break; - } - - if (fmtx->Samples.wValidBitsPerSample != fmt->wBitsPerSample && - !(fmt->wBitsPerSample == 32 && - fmtx->Samples.wValidBitsPerSample == 24)) { - ret = S_FALSE; - break; - } - } else { - ret = AUDCLNT_E_UNSUPPORTED_FORMAT; - break; - } - break; - - case WAVE_FORMAT_ALAW: - case WAVE_FORMAT_MULAW: - if (fmt->wBitsPerSample != 8) { - ret = E_INVALIDARG; - break; - } - /* Fall-through */ - case WAVE_FORMAT_IEEE_FLOAT: - if (fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT && fmt->wBitsPerSample != 32) { - ret = E_INVALIDARG; - break; - } - /* Fall-through */ - case WAVE_FORMAT_PCM: - if (fmt->wFormatTag == WAVE_FORMAT_PCM && - (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8)) { - ret = E_INVALIDARG; - break; - } - - if (fmt->nChannels > 2) { - ret = AUDCLNT_E_UNSUPPORTED_FORMAT; - break; - } - - /* fmt->cbSize, fmt->nBlockAlign and fmt->nAvgBytesPerSec seem to be - * ignored, invalid values are happily accepted. */ - break; - - default: + else if (fmt2.Format.nChannels == 0 || fmt2.Format.nSamplesPerSec == 0) + ret = E_INVALIDARG; + else if (fmt2.Format.nBlockAlign != fmt2.Format.nChannels * fmt2.Format.wBitsPerSample / 8) + ret = E_INVALIDARG; + else if (fmt2.Format.nAvgBytesPerSec != fmt2.Format.nBlockAlign * fmt2.Format.nSamplesPerSec) + ret = E_INVALIDARG; + else if (fmt2.Samples.wValidBitsPerSample == 0) + ret = E_INVALIDARG; + else if (fmt2.Samples.wValidBitsPerSample > fmt2.Format.wBitsPerSample) + ret = E_INVALIDARG; + else if (IsEqualGUID(&fmt2.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) + { + if (fmt2.Format.wBitsPerSample != 8 && fmt2.Format.wBitsPerSample != 16 + && fmt2.Format.wBitsPerSample != 24 && fmt2.Format.wBitsPerSample != 32) + ret = E_INVALIDARG; + else if (fmt2.Format.wBitsPerSample == 32 && fmt2.Samples.wValidBitsPerSample == 24) + ret = S_OK; + else if (fmt2.Samples.wValidBitsPerSample != fmt2.Format.wBitsPerSample) ret = AUDCLNT_E_UNSUPPORTED_FORMAT; - break; + else + ret = S_OK; } + else if (IsEqualGUID(&fmt2.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + { + if (fmt2.Format.wBitsPerSample != 32 && fmt2.Format.wBitsPerSample != 64) + ret = E_INVALIDARG; + else if (fmt2.Format.wBitsPerSample != 32) + ret = AUDCLNT_E_UNSUPPORTED_FORMAT; + else if (fmt2.Samples.wValidBitsPerSample != fmt2.Format.wBitsPerSample) + ret = AUDCLNT_E_UNSUPPORTED_FORMAT; + else + ret = S_OK; + } + else + ret = AUDCLNT_E_UNSUPPORTED_FORMAT; + + if (!compatible && ret == S_OK) + ret = AUDCLNT_E_UNSUPPORTED_FORMAT; return ret; } @@ -487,6 +434,7 @@ static HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_ struct create_stream_params params; UINT32 i, channel_count; stream_handle stream; + BOOL compatible; WCHAR *name; HRESULT hr; @@ -514,10 +462,32 @@ static HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_ if (flags & AUDCLNT_STREAMFLAGS_CROSSPROCESS) FIXME("Cross-process sessions not supported\n"); - hr = validate_wfx(fmt, mode); + if (mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) + return E_INVALIDARG; + + if (mode == AUDCLNT_SHAREMODE_EXCLUSIVE) { + if (flags & AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) + return E_INVALIDARG; + + compatible = TRUE; + } else { + WAVEFORMATEX *mix_fmt; + + if (FAILED(hr = IAudioClient3_GetMixFormat(&client->IAudioClient3_iface, &mix_fmt))) + return hr; + + if (flags & AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) + compatible = TRUE; + else if (flags & AUDCLNT_STREAMFLAGS_RATEADJUST) + compatible = fmt->nChannels == mix_fmt->nChannels; + else + compatible = fmt->nSamplesPerSec == mix_fmt->nSamplesPerSec && fmt->nChannels == mix_fmt->nChannels; + + CoTaskMemFree(mix_fmt); + } + + hr = validate_fmt((const WAVEFORMATEXTENSIBLE *)fmt, compatible); - if (hr == S_FALSE) - hr = AUDCLNT_E_UNSUPPORTED_FORMAT; if (hr != S_OK) return hr; @@ -880,6 +850,7 @@ static HRESULT WINAPI client_IsFormatSupported(IAudioClient3 *iface, AUDCLNT_SHA { struct audio_client *This = impl_from_IAudioClient3(iface); struct is_format_supported_params params; + BOOL compatible; HRESULT hr; TRACE("(%p)->(%x, %p, %p)\n", This, mode, fmt, out); @@ -892,7 +863,26 @@ static HRESULT WINAPI client_IsFormatSupported(IAudioClient3 *iface, AUDCLNT_SHA dump_fmt(fmt); - hr = validate_wfx(fmt, mode); + if (mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) + return E_INVALIDARG; + + if (mode == AUDCLNT_SHAREMODE_EXCLUSIVE) { + compatible = TRUE; + } else { + WAVEFORMATEX *mix_fmt; + + if (FAILED(hr = IAudioClient3_GetMixFormat(iface, &mix_fmt))) + return hr; + + compatible = fmt->nSamplesPerSec == mix_fmt->nSamplesPerSec && fmt->nChannels == mix_fmt->nChannels; + + CoTaskMemFree(mix_fmt); + } + + hr = validate_fmt((const WAVEFORMATEXTENSIBLE *)fmt, TRUE); + + if (hr == S_OK && !compatible) + hr = S_FALSE; if (FAILED(hr)) return hr; diff --git a/dlls/mmdevapi/tests/capture.c b/dlls/mmdevapi/tests/capture.c index 34e47b56fb1..f14882997f4 100644 --- a/dlls/mmdevapi/tests/capture.c +++ b/dlls/mmdevapi/tests/capture.c @@ -563,10 +563,41 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) IAudioClient *ac; HRESULT hr, hrs, expected; WAVEFORMATEX *pwfx, *pwfx2; - BOOL compatible, extensible; + BOOL compatible, extensible, channel_mismatch = FALSE, fmt24on32; extensible = fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE; + if (extensible) + { + switch (fmt->Format.nChannels) + { + case 1: + channel_mismatch = fmt->dwChannelMask != KSAUDIO_SPEAKER_MONO; + break; + + case 2: + channel_mismatch = fmt->dwChannelMask != KSAUDIO_SPEAKER_STEREO; + break; + + case 4: + channel_mismatch = fmt->dwChannelMask != KSAUDIO_SPEAKER_QUAD; + break; + + case 6: + channel_mismatch = fmt->dwChannelMask != KSAUDIO_SPEAKER_5POINT1; + break; + + case 8: + channel_mismatch = fmt->dwChannelMask != KSAUDIO_SPEAKER_7POINT1_SURROUND + && fmt->dwChannelMask != KSAUDIO_SPEAKER_7POINT1; + break; + } + } + + /* Some Wine drivers do not support 24-on-32 bits. */ + fmt24on32 = fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && fmt->Format.wBitsPerSample == 32 + && fmt->Samples.wValidBitsPerSample == 24; + hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, (void**)&ac); ok(hr == S_OK, "Activation failed with %08lx\n", hr); @@ -598,14 +629,12 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) /* Correct formats should be accepted, possibly with S_FALSE if they are not compatible. */ if (!compatible) expected = S_FALSE; - todo_wine_if(hr != expected) ok(hr == expected, "IsFormatSupported() returns %08lx, expected %08lx\n", hr, expected); } else { /* With incorrect formats it's a mess. Native emits all sorts of possible * error codes, including S_OK and S_FALSE, without any apparent logic. * I tried to find some regularity, but it seems hopeless. Also different * drivers do wildly different things. */ - todo_wine_if(SUCCEEDED(hr)) ok(hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == E_INVALIDARG || broken(hr == S_OK || hr == S_FALSE), "IsFormatSupported() returns %08lx\n", hr); } @@ -630,7 +659,7 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) if (mode == AUDCLNT_SHAREMODE_SHARED) { compatible = fmt->Format.nSamplesPerSec == pwfx->nSamplesPerSec && fmt->Format.nChannels == pwfx->nChannels; expected = validate_fmt(fmt, compatible); - todo_wine_if(hr != expected) + todo_wine_if(hr != expected && fmt24on32) ok(hr == expected, "Initialize() returns %08lx, expected %08lx\n", hr, expected); } else if (hrs == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED) /* Unsupported format implies "create failed" and shadows "not allowed" */ @@ -638,7 +667,8 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) "Initialize() returns %08lx(%08lx)\n", hr, hrs); else /* For some drivers Initialize() doesn't match IsFormatSupported(). */ - todo_wine_if(hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED || (hr == S_OK && hrs != S_OK)) + todo_wine_if(hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED + || (hr == AUDCLNT_E_UNSUPPORTED_FORMAT && hrs == S_OK && channel_mismatch)) ok(hrs == S_OK ? hr == S_OK || broken(hr == E_INVALIDARG) : hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == E_INVALIDARG, "Initialize() returns %08lx\n", hr); @@ -659,7 +689,7 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) if (mode == AUDCLNT_SHAREMODE_SHARED) { compatible = fmt->Format.nChannels == pwfx->nChannels; expected = validate_fmt(fmt, compatible); - todo_wine_if(hr != expected) + todo_wine_if(hr != expected && fmt24on32) ok(hr == expected, "Initialize(RATEADJUST) returns %08lx, expected %08lx\n", hr, expected); } else if (hrs == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED) /* Unsupported format implies "create failed" and shadows "not allowed" */ @@ -667,7 +697,8 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) "Initialize() returns %08lx(%08lx)\n", hr, hrs); else /* For some drivers Initialize() doesn't match IsFormatSupported(). */ - todo_wine_if(hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED || (hr == S_OK && hrs != S_OK)) + todo_wine_if(hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED + || (hr == AUDCLNT_E_UNSUPPORTED_FORMAT && hrs == S_OK && channel_mismatch)) ok(hrs == S_OK ? hr == S_OK || broken(hr == E_INVALIDARG) : hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == E_INVALIDARG, "Initialize() returns %08lx\n", hr); @@ -684,10 +715,9 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) hr = IAudioClient_Initialize(ac, mode, AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM, 5000000, 0, (WAVEFORMATEX*)fmt, NULL); if (mode == AUDCLNT_SHAREMODE_SHARED) { expected = validate_fmt(fmt, TRUE); - todo_wine_if(hr != expected) + todo_wine_if(hr != expected && (channel_mismatch || fmt24on32)) ok(hr == expected, "Initialize(AUTOCONVERTPCM) returns %08lx\n", hr); } else { - todo_wine_if(hr != E_INVALIDARG) ok(hr == E_INVALIDARG, "Initialize(AUTOCONVERTPCM) returns %08lx\n", hr); } diff --git a/dlls/mmdevapi/tests/render.c b/dlls/mmdevapi/tests/render.c index 790a33a73a8..bc3f7f22fca 100644 --- a/dlls/mmdevapi/tests/render.c +++ b/dlls/mmdevapi/tests/render.c @@ -789,6 +789,7 @@ void fill_wave_formats(const WAVEFORMATEXTENSIBLE *base_fmt) fmt->Format.cbSize -= 1; } +/* Identical to dlls/mmdevapi/client.c. */ HRESULT validate_fmt(const WAVEFORMATEXTENSIBLE *fmt, BOOL compatible) { WAVEFORMATEXTENSIBLE fmt2 = *fmt; @@ -861,7 +862,7 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) IAudioClient *ac; HRESULT hr, hrs, expected; WAVEFORMATEX *pwfx, *pwfx2; - BOOL compatible, channel_mismatch = FALSE; + BOOL compatible, channel_mismatch = FALSE, fmt24on32; if (fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) { @@ -890,6 +891,10 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) } } + /* Some Wine drivers do not support 24-on-32 bits. */ + fmt24on32 = fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && fmt->Format.wBitsPerSample == 32 + && fmt->Samples.wValidBitsPerSample == 24; + hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, (void**)&ac); ok(hr == S_OK, "Activation failed with %08lx\n", hr); @@ -911,7 +916,6 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) /* Correct formats should be accepted, possibly with S_FALSE if they are not compatible. */ if (!compatible) expected = S_FALSE; - todo_wine_if(hr != expected) ok(hr == expected || broken(hr == S_OK || (hr == S_FALSE && channel_mismatch)) /* Some drivers are more relaxed. */, "IsFormatSupported() returns %08lx, expected %08lx\n", hr, expected); } else { @@ -919,7 +923,6 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) * error codes, including S_OK and S_FALSE, without any apparent logic. * I tried to find some regularity, but it seems hopeless. Also different * drivers do wildly different things. */ - todo_wine_if(SUCCEEDED(hr)) ok(hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == E_INVALIDARG || broken(hr == S_OK || hr == S_FALSE), "IsFormatSupported() returns %08lx\n", hr); } @@ -944,15 +947,17 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) if (mode == AUDCLNT_SHAREMODE_SHARED) { compatible = fmt->Format.nSamplesPerSec == pwfx->nSamplesPerSec && fmt->Format.nChannels == pwfx->nChannels; expected = validate_fmt(fmt, compatible); - todo_wine_if(hr != expected) + todo_wine_if(hr != expected && (channel_mismatch || fmt24on32)) ok(hr == expected || broken(hr == S_OK) /* Some drivers are more relaxed. */, "Initialize() returns %08lx, expected %08lx\n", hr, expected); } else if (hrs == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED) /* Unsupported format implies "create failed" and shadows "not allowed" */ + todo_wine_if(hr == AUDCLNT_E_UNSUPPORTED_FORMAT && channel_mismatch) ok(hrs == hexcl && (hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == hrs), "Initialize() returns %08lx(%08lx)\n", hr, hrs); else /* For some drivers Initialize() doesn't match IsFormatSupported(). */ + todo_wine_if(hr == AUDCLNT_E_UNSUPPORTED_FORMAT && hrs == S_OK && channel_mismatch) ok(hrs == S_OK ? hr == S_OK || broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == E_INVALIDARG) : hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == E_INVALIDARG || broken(hr == S_OK), @@ -974,15 +979,17 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) if (mode == AUDCLNT_SHAREMODE_SHARED) { compatible = fmt->Format.nChannels == pwfx->nChannels; expected = validate_fmt(fmt, compatible); - todo_wine_if(hr != expected) + todo_wine_if(hr != expected && (channel_mismatch || fmt24on32)) ok(hr == expected || broken(hr == S_OK || (hr == AUDCLNT_E_UNSUPPORTED_FORMAT && channel_mismatch)) /* Some drivers are more relaxed. */, "Initialize(RATEADJUST) returns %08lx, expected %08lx\n", hr, expected); } else if (hrs == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED) /* Unsupported format implies "create failed" and shadows "not allowed" */ + todo_wine_if(hr == AUDCLNT_E_UNSUPPORTED_FORMAT && channel_mismatch) ok(hrs == hexcl && (hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == hrs), "Initialize(RATEADJUST) returns %08lx(%08lx)\n", hr, hrs); else /* For some drivers Initialize() doesn't match IsFormatSupported(). */ + todo_wine_if(hr == AUDCLNT_E_UNSUPPORTED_FORMAT && hrs == S_OK && channel_mismatch) ok(hrs == S_OK ? hr == S_OK || broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == E_INVALIDARG) : hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == E_INVALIDARG || broken(hr == S_OK), @@ -1000,10 +1007,9 @@ static void test_format(AUDCLNT_SHAREMODE mode, WAVEFORMATEXTENSIBLE *fmt) hr = IAudioClient_Initialize(ac, mode, AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM, 5000000, 0, (WAVEFORMATEX*)fmt, NULL); if (mode == AUDCLNT_SHAREMODE_SHARED) { expected = validate_fmt(fmt, TRUE); - todo_wine_if(hr != expected) + todo_wine_if(hr != expected && (channel_mismatch || fmt24on32)) ok(hr == expected, "Initialize(AUTOCONVERTPCM) returns %08lx, expected %08lx\n", hr, expected); } else { - todo_wine_if(hr != E_INVALIDARG) ok(hr == E_INVALIDARG, "Initialize(AUTOCONVERTPCM) returns %08lx\n", hr); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10243
participants (2)
-
Giovanni Mascellani -
Giovanni Mascellani (@giomasce)