From d4a2f4d44bdfa93231b9cf91e851b765c115755c Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Wed, 6 Apr 2022 07:55:58 +0100 Subject: [PATCH] wineoss: Move get_mix_format to the unixlib. Signed-off-by: Huw Davies Signed-off-by: Andrew Eikum Signed-off-by: Alexandre Julliard --- dlls/wineoss.drv/mmdevdrv.c | 104 +++++------------------------------- dlls/wineoss.drv/oss.c | 101 ++++++++++++++++++++++++++++++++++ dlls/wineoss.drv/unixlib.h | 9 ++++ 3 files changed, 122 insertions(+), 92 deletions(-) diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index 6ab7b3e551d..f7c7864e2af 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -1111,9 +1111,7 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface, WAVEFORMATEX **pwfx) { ACImpl *This = impl_from_IAudioClient3(iface); - WAVEFORMATEXTENSIBLE *fmt; - oss_audioinfo ai; - int formats, fd; + struct get_mix_format_params params; TRACE("(%p)->(%p)\n", This, pwfx); @@ -1121,99 +1119,21 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface, return E_POINTER; *pwfx = NULL; - fd = open_device(This->devnode, This->dataflow); - if(fd < 0){ - WARN("Unable to open device %s: %d (%s)\n", This->devnode, errno, strerror(errno)); - return AUDCLNT_E_DEVICE_INVALIDATED; - } - - ai.dev = -1; - if(ioctl(fd, SNDCTL_ENGINEINFO, &ai) < 0){ - WARN("Unable to get audio info for device %s: %d (%s)\n", This->devnode, - errno, strerror(errno)); - close(fd); - return E_FAIL; - } - close(fd); - - if(This->dataflow == eRender) - formats = ai.oformats; - else if(This->dataflow == eCapture) - formats = ai.iformats; - else - return E_UNEXPECTED; - - fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE)); - if(!fmt) + params.device = This->devnode; + params.flow = This->dataflow; + params.fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE)); + if(!params.fmt) return E_OUTOFMEMORY; - fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - if(formats & AFMT_S16_LE){ - fmt->Format.wBitsPerSample = 16; - fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; -#ifdef AFMT_FLOAT - }else if(formats & AFMT_FLOAT){ - fmt->Format.wBitsPerSample = 32; - fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; -#endif - }else if(formats & AFMT_U8){ - fmt->Format.wBitsPerSample = 8; - fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - }else if(formats & AFMT_S32_LE){ - fmt->Format.wBitsPerSample = 32; - fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - }else if(formats & AFMT_S24_LE){ - fmt->Format.wBitsPerSample = 24; - fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - }else{ - WARN("Didn't recognize any available OSS formats: %x\n", formats); - CoTaskMemFree(fmt); - return E_FAIL; - } + OSS_CALL(get_mix_format, ¶ms); - /* some OSS drivers are buggy, so set reasonable defaults if - * the reported values seem wacky */ - fmt->Format.nChannels = max(ai.max_channels, ai.min_channels); - if(fmt->Format.nChannels == 0 || fmt->Format.nChannels > 8) - fmt->Format.nChannels = 2; + if(SUCCEEDED(params.result)){ + *pwfx = ¶ms.fmt->Format; + dump_fmt(*pwfx); + } else + CoTaskMemFree(params.fmt); - /* For most hardware on Windows, users must choose a configuration with an even - * number of channels (stereo, quad, 5.1, 7.1). Users can then disable - * channels, but those channels are still reported to applications from - * GetMixFormat! Some applications behave badly if given an odd number of - * channels (e.g. 2.1). */ - if(fmt->Format.nChannels > 1 && (fmt->Format.nChannels & 0x1)) - { - if(fmt->Format.nChannels < ai.max_channels) - fmt->Format.nChannels += 1; - else - /* We could "fake" more channels and downmix the emulated channels, - * but at that point you really ought to tweak your OSS setup or - * just use PulseAudio. */ - WARN("Some Windows applications behave badly with an odd number of channels (%u)!\n", fmt->Format.nChannels); - } - - if(ai.max_rate == 0) - fmt->Format.nSamplesPerSec = 44100; - else - fmt->Format.nSamplesPerSec = min(ai.max_rate, 44100); - if(fmt->Format.nSamplesPerSec < ai.min_rate) - fmt->Format.nSamplesPerSec = ai.min_rate; - - fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels); - - fmt->Format.nBlockAlign = (fmt->Format.wBitsPerSample * - fmt->Format.nChannels) / 8; - fmt->Format.nAvgBytesPerSec = fmt->Format.nSamplesPerSec * - fmt->Format.nBlockAlign; - - fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample; - fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); - - *pwfx = (WAVEFORMATEX*)fmt; - dump_fmt(*pwfx); - - return S_OK; + return params.result; } static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface, diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c index 49173ec6b6b..389ec73ee10 100644 --- a/dlls/wineoss.drv/oss.c +++ b/dlls/wineoss.drv/oss.c @@ -495,9 +495,110 @@ static NTSTATUS is_format_supported(void *args) return STATUS_SUCCESS; } +static NTSTATUS get_mix_format(void *args) +{ + struct get_mix_format_params *params = args; + WAVEFORMATEXTENSIBLE *fmt = params->fmt; + oss_audioinfo ai; + int formats, fd; + + if(params->flow != eRender && params->flow != eCapture){ + params->result = E_UNEXPECTED; + return STATUS_SUCCESS; + } + + fd = open_device(params->device, params->flow); + if(fd < 0){ + WARN("Unable to open device %s: %d (%s)\n", params->device, errno, strerror(errno)); + params->result = AUDCLNT_E_DEVICE_INVALIDATED; + return STATUS_SUCCESS; + } + + ai.dev = -1; + if(ioctl(fd, SNDCTL_ENGINEINFO, &ai) < 0){ + WARN("Unable to get audio info for device %s: %d (%s)\n", params->device, errno, strerror(errno)); + close(fd); + params->result = E_FAIL; + return STATUS_SUCCESS; + } + close(fd); + + if(params->flow == eRender) + formats = ai.oformats; + else + formats = ai.iformats; + + fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + if(formats & AFMT_S16_LE){ + fmt->Format.wBitsPerSample = 16; + fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; +#ifdef AFMT_FLOAT + }else if(formats & AFMT_FLOAT){ + fmt->Format.wBitsPerSample = 32; + fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; +#endif + }else if(formats & AFMT_U8){ + fmt->Format.wBitsPerSample = 8; + fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + }else if(formats & AFMT_S32_LE){ + fmt->Format.wBitsPerSample = 32; + fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + }else if(formats & AFMT_S24_LE){ + fmt->Format.wBitsPerSample = 24; + fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + }else{ + WARN("Didn't recognize any available OSS formats: %x\n", formats); + params->result = E_FAIL; + return STATUS_SUCCESS; + } + + /* some OSS drivers are buggy, so set reasonable defaults if + * the reported values seem wacky */ + fmt->Format.nChannels = max(ai.max_channels, ai.min_channels); + if(fmt->Format.nChannels == 0 || fmt->Format.nChannels > 8) + fmt->Format.nChannels = 2; + + /* For most hardware on Windows, users must choose a configuration with an even + * number of channels (stereo, quad, 5.1, 7.1). Users can then disable + * channels, but those channels are still reported to applications from + * GetMixFormat! Some applications behave badly if given an odd number of + * channels (e.g. 2.1). */ + if(fmt->Format.nChannels > 1 && (fmt->Format.nChannels & 0x1)) + { + if(fmt->Format.nChannels < ai.max_channels) + fmt->Format.nChannels += 1; + else + /* We could "fake" more channels and downmix the emulated channels, + * but at that point you really ought to tweak your OSS setup or + * just use PulseAudio. */ + WARN("Some Windows applications behave badly with an odd number of channels (%u)!\n", fmt->Format.nChannels); + } + + if(ai.max_rate == 0) + fmt->Format.nSamplesPerSec = 44100; + else + fmt->Format.nSamplesPerSec = min(ai.max_rate, 44100); + if(fmt->Format.nSamplesPerSec < ai.min_rate) + fmt->Format.nSamplesPerSec = ai.min_rate; + + fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels); + + fmt->Format.nBlockAlign = (fmt->Format.wBitsPerSample * + fmt->Format.nChannels) / 8; + fmt->Format.nAvgBytesPerSec = fmt->Format.nSamplesPerSec * + fmt->Format.nBlockAlign; + + fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample; + fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + + params->result = S_OK; + return STATUS_SUCCESS; +} + unixlib_entry_t __wine_unix_call_funcs[] = { test_connect, get_endpoint_ids, is_format_supported, + get_mix_format, }; diff --git a/dlls/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h index b89e2142d93..e0817cbc9c1 100644 --- a/dlls/wineoss.drv/unixlib.h +++ b/dlls/wineoss.drv/unixlib.h @@ -77,11 +77,20 @@ struct is_format_supported_params HRESULT result; }; +struct get_mix_format_params +{ + const char *device; + EDataFlow flow; + WAVEFORMATEXTENSIBLE *fmt; + HRESULT result; +}; + enum oss_funcs { oss_test_connect, oss_get_endpoint_ids, oss_is_format_supported, + oss_get_mix_format, }; extern unixlib_handle_t oss_handle;