[PATCH 01/12] winecoreaudio: Move is_format_supported to the unixlib.

Andrew Eikum aeikum at codeweavers.com
Tue Nov 23 09:22:05 CST 2021


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

On Tue, Nov 23, 2021 at 07:54:58AM +0000, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
>  dlls/winecoreaudio.drv/coreaudio.c |  65 ++++++++
>  dlls/winecoreaudio.drv/mmdevdrv.c  | 255 ++---------------------------
>  dlls/winecoreaudio.drv/unixlib.h   |  11 ++
>  3 files changed, 91 insertions(+), 240 deletions(-)
> 
> diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c
> index 208655d20c6..f7f7777efcb 100644
> --- a/dlls/winecoreaudio.drv/coreaudio.c
> +++ b/dlls/winecoreaudio.drv/coreaudio.c
> @@ -948,10 +948,75 @@ static NTSTATUS get_mix_format(void *args)
>      return STATUS_SUCCESS;
>  }
>  
> +static NTSTATUS 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;
> +
> +    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 if(params->fmt_in->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
> +        if(params->fmt_in->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
> +            params->result = E_INVALIDARG;
> +        else if(params->fmt_in->nAvgBytesPerSec == 0 || params->fmt_in->nBlockAlign == 0 ||
> +                fmtex->Samples.wValidBitsPerSample > params->fmt_in->wBitsPerSample)
> +            params->result = E_INVALIDARG;
> +        else 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(FAILED(params->result)) return STATUS_SUCCESS;
> +
> +    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;
> +
> +    if(params->fmt_in->nChannels == 0){
> +        params->result = AUDCLNT_E_UNSUPPORTED_FORMAT;
> +        return STATUS_SUCCESS;
> +    }
> +    unit = get_audiounit(params->flow, params->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 =
> +        {
> +            .flow = params->flow,
> +            .dev_id = params->dev_id,
> +            .fmt = params->fmt_out,
> +        };
> +
> +        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;
> +}
> +
>  unixlib_entry_t __wine_unix_call_funcs[] =
>  {
>      get_endpoint_ids,
>      create_stream,
>      release_stream,
>      get_mix_format,
> +    is_format_supported,
>  };
> diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
> index 2ad2938a5d8..418bbfa00af 100644
> --- a/dlls/winecoreaudio.drv/mmdevdrv.c
> +++ b/dlls/winecoreaudio.drv/mmdevdrv.c
> @@ -473,62 +473,6 @@ static BOOL get_deviceid_by_guid(GUID *guid, AudioDeviceID *id, EDataFlow *flow)
>      return FALSE;
>  }
>  
> -static AudioComponentInstance get_audiounit(EDataFlow dataflow, AudioDeviceID adevid)
> -{
> -    AudioComponentInstance unit;
> -    AudioComponent comp;
> -    AudioComponentDescription desc;
> -    OSStatus sc;
> -
> -    memset(&desc, 0, sizeof(desc));
> -    desc.componentType = kAudioUnitType_Output;
> -    desc.componentSubType = kAudioUnitSubType_HALOutput;
> -    desc.componentManufacturer = kAudioUnitManufacturer_Apple;
> -
> -    if(!(comp = AudioComponentFindNext(NULL, &desc))){
> -        WARN("AudioComponentFindNext failed\n");
> -        return NULL;
> -    }
> -
> -    sc = AudioComponentInstanceNew(comp, &unit);
> -    if(sc != noErr){
> -        WARN("AudioComponentInstanceNew failed: %x\n", (int)sc);
> -        return NULL;
> -    }
> -
> -    if(dataflow == eCapture){
> -        UInt32 enableio;
> -
> -        enableio = 1;
> -        sc = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO,
> -                kAudioUnitScope_Input, 1, &enableio, sizeof(enableio));
> -        if(sc != noErr){
> -            WARN("Couldn't enable I/O on input element: %x\n", (int)sc);
> -            AudioComponentInstanceDispose(unit);
> -            return NULL;
> -        }
> -
> -        enableio = 0;
> -        sc = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO,
> -                kAudioUnitScope_Output, 0, &enableio, sizeof(enableio));
> -        if(sc != noErr){
> -            WARN("Couldn't disable I/O on output element: %x\n", (int)sc);
> -            AudioComponentInstanceDispose(unit);
> -            return NULL;
> -        }
> -    }
> -
> -    sc = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_CurrentDevice,
> -            kAudioUnitScope_Global, 0, &adevid, sizeof(adevid));
> -    if(sc != noErr){
> -        WARN("Couldn't set audio unit device\n");
> -        AudioComponentInstanceDispose(unit);
> -        return NULL;
> -    }
> -
> -    return unit;
> -}
> -
>  HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient **out)
>  {
>      ACImpl *This;
> @@ -689,46 +633,6 @@ static void dump_fmt(const WAVEFORMATEX *fmt)
>      }
>  }
>  
> -static HRESULT ca_get_audiodesc(AudioStreamBasicDescription *desc,
> -        const WAVEFORMATEX *fmt)
> -{
> -    const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
> -
> -    desc->mFormatFlags = 0;
> -
> -    if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
> -            (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> -             IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
> -        desc->mFormatID = kAudioFormatLinearPCM;
> -        if(fmt->wBitsPerSample > 8)
> -            desc->mFormatFlags = kAudioFormatFlagIsSignedInteger;
> -    }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
> -            (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> -             IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
> -        desc->mFormatID = kAudioFormatLinearPCM;
> -        desc->mFormatFlags = kAudioFormatFlagIsFloat;
> -    }else if(fmt->wFormatTag == WAVE_FORMAT_MULAW ||
> -            (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> -             IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_MULAW))){
> -        desc->mFormatID = kAudioFormatULaw;
> -    }else if(fmt->wFormatTag == WAVE_FORMAT_ALAW ||
> -            (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> -             IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_ALAW))){
> -        desc->mFormatID = kAudioFormatALaw;
> -    }else
> -        return AUDCLNT_E_UNSUPPORTED_FORMAT;
> -
> -    desc->mSampleRate = fmt->nSamplesPerSec;
> -    desc->mBytesPerPacket = fmt->nBlockAlign;
> -    desc->mFramesPerPacket = 1;
> -    desc->mBytesPerFrame = fmt->nBlockAlign;
> -    desc->mChannelsPerFrame = fmt->nChannels;
> -    desc->mBitsPerChannel = fmt->wBitsPerSample;
> -    desc->mReserved = 0;
> -
> -    return S_OK;
> -}
> -
>  static void session_init_vols(AudioSession *session, UINT channels)
>  {
>      if(session->channel_count < channels){
> @@ -931,90 +835,6 @@ static void capture_resample(ACImpl *This)
>      }
>  }
>  
> -static void dump_adesc(const char *aux, AudioStreamBasicDescription *desc)
> -{
> -    TRACE("%s: mSampleRate: %f\n", aux, desc->mSampleRate);
> -    TRACE("%s: mBytesPerPacket: %u\n", aux, (unsigned int)desc->mBytesPerPacket);
> -    TRACE("%s: mFramesPerPacket: %u\n", aux, (unsigned int)desc->mFramesPerPacket);
> -    TRACE("%s: mBytesPerFrame: %u\n", aux, (unsigned int)desc->mBytesPerFrame);
> -    TRACE("%s: mChannelsPerFrame: %u\n", aux, (unsigned int)desc->mChannelsPerFrame);
> -    TRACE("%s: mBitsPerChannel: %u\n", aux, (unsigned int)desc->mBitsPerChannel);
> -}
> -
> -static HRESULT ca_setup_audiounit(EDataFlow dataflow, AudioComponentInstance unit,
> -        const WAVEFORMATEX *fmt, AudioStreamBasicDescription *dev_desc,
> -        AudioConverterRef *converter)
> -{
> -    OSStatus sc;
> -    HRESULT hr;
> -
> -    if(dataflow == eCapture){
> -        AudioStreamBasicDescription desc;
> -        UInt32 size;
> -        Float64 rate;
> -        fenv_t fenv;
> -        BOOL fenv_stored = TRUE;
> -
> -        hr = ca_get_audiodesc(&desc, fmt);
> -        if(FAILED(hr))
> -            return hr;
> -        dump_adesc("requested", &desc);
> -
> -        /* input-only units can't perform sample rate conversion, so we have to
> -         * set up our own AudioConverter to support arbitrary sample rates. */
> -        size = sizeof(*dev_desc);
> -        sc = AudioUnitGetProperty(unit, kAudioUnitProperty_StreamFormat,
> -                kAudioUnitScope_Input, 1, dev_desc, &size);
> -        if(sc != noErr){
> -            WARN("Couldn't get unit format: %x\n", (int)sc);
> -            return osstatus_to_hresult(sc);
> -        }
> -        dump_adesc("hardware", dev_desc);
> -
> -        rate = dev_desc->mSampleRate;
> -        *dev_desc = desc;
> -        dev_desc->mSampleRate = rate;
> -
> -        dump_adesc("final", dev_desc);
> -        sc = AudioUnitSetProperty(unit, kAudioUnitProperty_StreamFormat,
> -                kAudioUnitScope_Output, 1, dev_desc, sizeof(*dev_desc));
> -        if(sc != noErr){
> -            WARN("Couldn't set unit format: %x\n", (int)sc);
> -            return osstatus_to_hresult(sc);
> -        }
> -
> -        /* AudioConverterNew requires divide-by-zero SSE exceptions to be masked */
> -        if(feholdexcept(&fenv)){
> -            WARN("Failed to store fenv state\n");
> -            fenv_stored = FALSE;
> -        }
> -
> -        sc = AudioConverterNew(dev_desc, &desc, converter);
> -
> -        if(fenv_stored && fesetenv(&fenv))
> -            WARN("Failed to restore fenv state\n");
> -
> -        if(sc != noErr){
> -            WARN("Couldn't create audio converter: %x\n", (int)sc);
> -            return osstatus_to_hresult(sc);
> -        }
> -    }else{
> -        hr = ca_get_audiodesc(dev_desc, fmt);
> -        if(FAILED(hr))
> -            return hr;
> -
> -        dump_adesc("final", dev_desc);
> -        sc = AudioUnitSetProperty(unit, kAudioUnitProperty_StreamFormat,
> -                kAudioUnitScope_Input, 0, dev_desc, sizeof(*dev_desc));
> -        if(sc != noErr){
> -            WARN("Couldn't set format: %x\n", (int)sc);
> -            return osstatus_to_hresult(sc);
> -        }
> -    }
> -
> -    return S_OK;
> -}
> -
>  static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>          AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration,
>          REFERENCE_TIME period, const WAVEFORMATEX *fmt,
> @@ -1298,75 +1118,30 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface,
>          WAVEFORMATEX **outpwfx)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> -    AudioStreamBasicDescription dev_desc;
> -    AudioConverterRef converter;
> -    AudioComponentInstance unit;
> -    WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)pwfx;
> -    HRESULT hr;
> +    struct is_format_supported_params params;
>  
>      TRACE("(%p)->(%x, %p, %p)\n", This, mode, pwfx, outpwfx);
> +    if(pwfx) dump_fmt(pwfx);
>  
> -    if(!pwfx || (mode == AUDCLNT_SHAREMODE_SHARED && !outpwfx))
> -        return E_POINTER;
> -
> -    if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
> -        return E_INVALIDARG;
> -
> -    if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> -            pwfx->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
> -        return E_INVALIDARG;
> -
> -    dump_fmt(pwfx);
> +    params.dev_id = This->adevid;
> +    params.flow = This->dataflow;
> +    params.share = mode;
> +    params.fmt_in = pwfx;
> +    params.fmt_out = NULL;
>  
>      if(outpwfx){
>          *outpwfx = NULL;
> -        if(mode != AUDCLNT_SHAREMODE_SHARED)
> -            outpwfx = NULL;
> -    }
> -
> -    if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
> -        if(pwfx->nAvgBytesPerSec == 0 ||
> -                pwfx->nBlockAlign == 0 ||
> -                fmtex->Samples.wValidBitsPerSample > pwfx->wBitsPerSample)
> -            return E_INVALIDARG;
> -        if(fmtex->Samples.wValidBitsPerSample < pwfx->wBitsPerSample)
> -            goto unsupported;
> -        if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE){
> -            if(fmtex->dwChannelMask == 0 ||
> -                    fmtex->dwChannelMask & SPEAKER_RESERVED)
> -                goto unsupported;
> -        }
> +        if(mode == AUDCLNT_SHAREMODE_SHARED)
> +            params.fmt_out = CoTaskMemAlloc(sizeof(*params.fmt_out));
>      }
> +    UNIX_CALL(is_format_supported, &params);
>  
> -    if(pwfx->nBlockAlign != pwfx->nChannels * pwfx->wBitsPerSample / 8 ||
> -            pwfx->nAvgBytesPerSec != pwfx->nBlockAlign * pwfx->nSamplesPerSec)
> -        goto unsupported;
> -
> -    if(pwfx->nChannels == 0)
> -        return AUDCLNT_E_UNSUPPORTED_FORMAT;
> -
> -    unit = get_audiounit(This->dataflow, This->adevid);
> -
> -    converter = NULL;
> -    hr = ca_setup_audiounit(This->dataflow, unit, pwfx, &dev_desc, &converter);
> -    AudioComponentInstanceDispose(unit);
> -    if(FAILED(hr))
> -        goto unsupported;
> -
> -    if(converter)
> -        AudioConverterDispose(converter);
> -
> -    return S_OK;
> -
> -unsupported:
> -    if(outpwfx){
> -        hr = IAudioClient3_GetMixFormat(&This->IAudioClient3_iface, outpwfx);
> -        if(FAILED(hr))
> -            return hr;
> -        return S_FALSE;
> -    }
> +    if(params.result == S_FALSE)
> +        *outpwfx = &params.fmt_out->Format;
> +    else
> +        CoTaskMemFree(params.fmt_out);
>  
> -    return AUDCLNT_E_UNSUPPORTED_FORMAT;
> +    return params.result;
>  }
>  
>  static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface,
> diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h
> index e247b789d55..23de92ecfdd 100644
> --- a/dlls/winecoreaudio.drv/unixlib.h
> +++ b/dlls/winecoreaudio.drv/unixlib.h
> @@ -83,12 +83,23 @@ struct get_mix_format_params
>      HRESULT result;
>  };
>  
> +struct is_format_supported_params
> +{
> +    EDataFlow flow;
> +    DWORD dev_id;
> +    AUDCLNT_SHAREMODE share;
> +    const WAVEFORMATEX *fmt_in;
> +    WAVEFORMATEXTENSIBLE *fmt_out;
> +    HRESULT result;
> +};
> +
>  enum unix_funcs
>  {
>      unix_get_endpoint_ids,
>      unix_create_stream,
>      unix_release_stream,
>      unix_get_mix_format,
> +    unix_is_format_supported,
>  };
>  
>  extern unixlib_handle_t coreaudio_handle;
> -- 
> 2.23.0
> 
> 



More information about the wine-devel mailing list