[PATCH 8/8] wineoss: Move get_mix_format to the unixlib.

Andrew Eikum aeikum at codeweavers.com
Mon Apr 11 09:00:41 CDT 2022


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>

On Wed, Apr 06, 2022 at 07:55:58AM +0100, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
>  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;
> -    }
> -
> -    /* 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;
> +    OSS_CALL(get_mix_format, &params);
>  
> -    fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample;
> -    fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
> -
> -    *pwfx = (WAVEFORMATEX*)fmt;
> -    dump_fmt(*pwfx);
> +    if(SUCCEEDED(params.result)){
> +        *pwfx = &params.fmt->Format;
> +        dump_fmt(*pwfx);
> +    } else
> +        CoTaskMemFree(params.fmt);
>  
> -    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;
> -- 
> 2.25.1
> 
> 



More information about the wine-devel mailing list