From: Giovanni Mascellani gmascellani@codeweavers.com
According to the tests, it doesn't seem that the format suggested by IsFormatSupported() depends on the format supplied by the caller. It's just the mix format, so there is no need to have specialized handling for each driver. --- dlls/mmdevapi/client.c | 39 +++++---- dlls/mmdevapi/unixlib.h | 1 - dlls/winealsa.drv/alsa.c | 45 +--------- dlls/winecoreaudio.drv/coreaudio.c | 38 --------- dlls/winepulse.drv/pulse.c | 127 ++--------------------------- 5 files changed, 33 insertions(+), 217 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index fc3a0208f71..94d831370ab 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -894,26 +894,37 @@ static HRESULT WINAPI client_IsFormatSupported(IAudioClient3 *iface, AUDCLNT_SHA
dump_fmt(fmt);
- if (FAILED(hr = validate_wfx(fmt, mode))) + hr = validate_wfx(fmt, mode); + + if (FAILED(hr)) return hr;
- params.device = This->device_name; - params.flow = This->dataflow; - params.share = mode; - params.fmt_in = fmt; - params.fmt_out = NULL; + if (hr == S_OK) { + params.device = This->device_name; + params.flow = This->dataflow; + params.share = mode; + params.fmt_in = fmt;
- if (out && mode == AUDCLNT_SHAREMODE_SHARED) - params.fmt_out = CoTaskMemAlloc(sizeof(*params.fmt_out)); + wine_unix_call(is_format_supported, ¶ms);
- wine_unix_call(is_format_supported, ¶ms); + hr = params.result; + }
- if (params.result == S_FALSE) - *out = ¶ms.fmt_out->Format; - else - CoTaskMemFree(params.fmt_out); + if (hr == S_FALSE) { + if (mode == AUDCLNT_SHAREMODE_EXCLUSIVE) { + return AUDCLNT_E_UNSUPPORTED_FORMAT; + } else { + if (FAILED(hr = IAudioClient3_GetMixFormat(iface, out))) + return hr; + return S_FALSE; + } + } + + if (hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED && This->dataflow == eCapture) + hr = AUDCLNT_E_UNSUPPORTED_FORMAT; + + return hr;
- return params.result; }
static HRESULT WINAPI client_GetMixFormat(IAudioClient3 *iface, WAVEFORMATEX **pwfx) diff --git a/dlls/mmdevapi/unixlib.h b/dlls/mmdevapi/unixlib.h index 033cd2085ea..3df13e93b39 100644 --- a/dlls/mmdevapi/unixlib.h +++ b/dlls/mmdevapi/unixlib.h @@ -136,7 +136,6 @@ struct is_format_supported_params EDataFlow flow; AUDCLNT_SHAREMODE share; const WAVEFORMATEX *fmt_in; - WAVEFORMATEXTENSIBLE *fmt_out; HRESULT result; };
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index 15805d2a1e9..524ede37172 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -1863,12 +1863,10 @@ static NTSTATUS alsa_release_capture_buffer(void *args) static NTSTATUS alsa_is_format_supported(void *args) { struct is_format_supported_params *params = args; - const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)params->fmt_in; snd_pcm_t *pcm_handle; snd_pcm_hw_params_t *hw_params; snd_pcm_format_mask_t *formats = NULL; snd_pcm_format_t format; - WAVEFORMATEXTENSIBLE *closest = NULL; unsigned int max = 0, min = 0; int err; int alsa_channels, alsa_channel_map[32]; @@ -1896,12 +1894,6 @@ static NTSTATUS alsa_is_format_supported(void *args) goto exit; }
- closest = clone_format(params->fmt_in); - if(!closest){ - params->result = E_OUTOFMEMORY; - goto exit; - } - if((err = snd_pcm_hw_params_get_rate_min(hw_params, &min, NULL)) < 0){ params->result = AUDCLNT_E_DEVICE_INVALIDATED; WARN("Unable to get min rate: %d (%s)\n", err, snd_strerror(err)); @@ -1930,47 +1922,17 @@ static NTSTATUS alsa_is_format_supported(void *args) WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err)); goto exit; } - if(params->fmt_in->nChannels > max){ + if(params->fmt_in->nChannels > max) params->result = S_FALSE; - closest->Format.nChannels = max; - }else if(params->fmt_in->nChannels < min){ + else if(params->fmt_in->nChannels < min) params->result = S_FALSE; - closest->Format.nChannels = min; - }
map_channels(params->flow, params->fmt_in, &alsa_channels, alsa_channel_map);
- if(alsa_channels > max){ - params->result = S_FALSE; - closest->Format.nChannels = max; - } - - if(closest->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) - closest->dwChannelMask = get_channel_mask(closest->Format.nChannels); - - if(params->fmt_in->nBlockAlign != params->fmt_in->nChannels * params->fmt_in->wBitsPerSample / 8 || - params->fmt_in->nAvgBytesPerSec != params->fmt_in->nBlockAlign * params->fmt_in->nSamplesPerSec || - (params->fmt_in->wFormatTag == WAVE_FORMAT_EXTENSIBLE && - fmtex->Samples.wValidBitsPerSample < params->fmt_in->wBitsPerSample)) + if(alsa_channels > max) params->result = S_FALSE;
- if(params->share == AUDCLNT_SHAREMODE_EXCLUSIVE && params->fmt_in->wFormatTag == WAVE_FORMAT_EXTENSIBLE){ - if(fmtex->dwChannelMask == 0 || fmtex->dwChannelMask & SPEAKER_RESERVED) - params->result = S_FALSE; - } - exit: - if(params->result == S_FALSE && !params->fmt_out) - params->result = AUDCLNT_E_UNSUPPORTED_FORMAT; - - if(params->result == S_FALSE) { - closest->Format.nBlockAlign = closest->Format.nChannels * closest->Format.wBitsPerSample / 8; - closest->Format.nAvgBytesPerSec = closest->Format.nBlockAlign * closest->Format.nSamplesPerSec; - if(closest->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) - closest->Samples.wValidBitsPerSample = closest->Format.wBitsPerSample; - memcpy(params->fmt_out, closest, closest->Format.cbSize); - } - free(closest); free(formats); free(hw_params); snd_pcm_close(pcm_handle); @@ -2657,7 +2619,6 @@ static NTSTATUS alsa_wow64_is_format_supported(void *args) .flow = params32->flow, .share = params32->share, .fmt_in = ULongToPtr(params32->fmt_in), - .fmt_out = ULongToPtr(params32->fmt_out) }; alsa_is_format_supported(¶ms); params32->result = params.result; diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index b19f7ba3854..947cf441f10 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -1094,55 +1094,18 @@ static NTSTATUS unix_get_mix_format(void *args) static NTSTATUS unix_is_format_supported(void *args) { struct is_format_supported_params *params = args; - const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)params->fmt_in; AudioStreamBasicDescription dev_desc; AudioConverterRef converter; AudioComponentInstance unit; const AudioDeviceID dev_id = dev_id_from_device(params->device);
- if(params->fmt_in->wFormatTag == WAVE_FORMAT_EXTENSIBLE) { - if (fmtex->Samples.wValidBitsPerSample < params->fmt_in->wBitsPerSample) - goto unsupported; - else if(params->share == AUDCLNT_SHAREMODE_EXCLUSIVE && - (fmtex->dwChannelMask == 0 || fmtex->dwChannelMask & SPEAKER_RESERVED)) - goto unsupported; - } - - if(params->fmt_in->nBlockAlign != params->fmt_in->nChannels * params->fmt_in->wBitsPerSample / 8 || - params->fmt_in->nAvgBytesPerSec != params->fmt_in->nBlockAlign * params->fmt_in->nSamplesPerSec) - goto unsupported; - - params->result = S_OK; - - if(params->fmt_in->nChannels == 0){ - params->result = AUDCLNT_E_UNSUPPORTED_FORMAT; - return STATUS_SUCCESS; - } unit = get_audiounit(params->flow, dev_id);
converter = NULL; params->result = ca_setup_audiounit(params->flow, unit, params->fmt_in, &dev_desc, &converter); AudioComponentInstanceDispose(unit); - if(FAILED(params->result)) goto unsupported; if(converter) AudioConverterDispose(converter);
- params->result = S_OK; - return STATUS_SUCCESS; - -unsupported: - if(params->fmt_out){ - struct get_mix_format_params get_mix_params = - { - .device = params->device, - .flow = params->flow, - .fmt = params->fmt_out, - }; - - unix_get_mix_format(&get_mix_params); - params->result = get_mix_params.result; - if(SUCCEEDED(params->result)) params->result = S_FALSE; - } - else params->result = AUDCLNT_E_UNSUPPORTED_FORMAT; return STATUS_SUCCESS; }
@@ -2007,7 +1970,6 @@ static NTSTATUS unix_wow64_is_format_supported(void *args) .flow = params32->flow, .share = params32->share, .fmt_in = ULongToPtr(params32->fmt_in), - .fmt_out = ULongToPtr(params32->fmt_out) }; unix_is_format_supported(¶ms); params32->result = params.result; diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 9129b224c44..6fabc396ebe 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -2069,128 +2069,12 @@ static NTSTATUS pulse_release_capture_buffer(void *args) 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; - - memcpy(&in, params->fmt_in, params->fmt_in->wFormatTag == WAVE_FORMAT_EXTENSIBLE ? - sizeof(in) : sizeof(in.Format)); - - if (exclusive) - out = ∈ - 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; - } - - if (exclusive) { /* This driver does not support exclusive mode. */ - if (params->result == S_OK) - params->result = params->flow == eCapture ? - AUDCLNT_E_UNSUPPORTED_FORMAT : - AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED; - else if (params->result == S_FALSE) - params->result = AUDCLNT_E_UNSUPPORTED_FORMAT; - } + /* This driver does not support exclusive mode. */ + if (params->share == AUDCLNT_SHAREMODE_EXCLUSIVE) + params->result = AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED; + else + params->result = S_OK;
return STATUS_SUCCESS; } @@ -2838,7 +2722,6 @@ static NTSTATUS pulse_wow64_is_format_supported(void *args) .flow = params32->flow, .share = params32->share, .fmt_in = ULongToPtr(params32->fmt_in), - .fmt_out = ULongToPtr(params32->fmt_out) }; pulse_is_format_supported(¶ms); params32->result = params.result;