[PATCH 7/7] winecoreaudio: Move get_mix_format to the unixlib.

Andrew Eikum aeikum at codeweavers.com
Mon Nov 22 14:55:24 CST 2021


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

On Thu, Nov 18, 2021 at 07:52:38AM +0000, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
>  dlls/winecoreaudio.drv/coreaudio.c | 246 +++++++++++++++++++++++++++
>  dlls/winecoreaudio.drv/mmdevdrv.c  | 256 ++---------------------------
>  dlls/winecoreaudio.drv/unixlib.h   |   9 +
>  3 files changed, 267 insertions(+), 244 deletions(-)
> 
> diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c
> index 3ab80efc4e2..208655d20c6 100644
> --- a/dlls/winecoreaudio.drv/coreaudio.c
> +++ b/dlls/winecoreaudio.drv/coreaudio.c
> @@ -703,9 +703,255 @@ static NTSTATUS release_stream( void *args )
>      return STATUS_SUCCESS;
>  }
>  
> +static DWORD ca_channel_layout_to_channel_mask(const AudioChannelLayout *layout)
> +{
> +    int i;
> +    DWORD mask = 0;
> +
> +    for (i = 0; i < layout->mNumberChannelDescriptions; ++i) {
> +        switch (layout->mChannelDescriptions[i].mChannelLabel) {
> +            default: FIXME("Unhandled channel 0x%x\n",
> +                           (unsigned int)layout->mChannelDescriptions[i].mChannelLabel); break;
> +            case kAudioChannelLabel_Left: mask |= SPEAKER_FRONT_LEFT; break;
> +            case kAudioChannelLabel_Mono:
> +            case kAudioChannelLabel_Center: mask |= SPEAKER_FRONT_CENTER; break;
> +            case kAudioChannelLabel_Right: mask |= SPEAKER_FRONT_RIGHT; break;
> +            case kAudioChannelLabel_LeftSurround: mask |= SPEAKER_BACK_LEFT; break;
> +            case kAudioChannelLabel_CenterSurround: mask |= SPEAKER_BACK_CENTER; break;
> +            case kAudioChannelLabel_RightSurround: mask |= SPEAKER_BACK_RIGHT; break;
> +            case kAudioChannelLabel_LFEScreen: mask |= SPEAKER_LOW_FREQUENCY; break;
> +            case kAudioChannelLabel_LeftSurroundDirect: mask |= SPEAKER_SIDE_LEFT; break;
> +            case kAudioChannelLabel_RightSurroundDirect: mask |= SPEAKER_SIDE_RIGHT; break;
> +            case kAudioChannelLabel_TopCenterSurround: mask |= SPEAKER_TOP_CENTER; break;
> +            case kAudioChannelLabel_VerticalHeightLeft: mask |= SPEAKER_TOP_FRONT_LEFT; break;
> +            case kAudioChannelLabel_VerticalHeightCenter: mask |= SPEAKER_TOP_FRONT_CENTER; break;
> +            case kAudioChannelLabel_VerticalHeightRight: mask |= SPEAKER_TOP_FRONT_RIGHT; break;
> +            case kAudioChannelLabel_TopBackLeft: mask |= SPEAKER_TOP_BACK_LEFT; break;
> +            case kAudioChannelLabel_TopBackCenter: mask |= SPEAKER_TOP_BACK_CENTER; break;
> +            case kAudioChannelLabel_TopBackRight: mask |= SPEAKER_TOP_BACK_RIGHT; break;
> +            case kAudioChannelLabel_LeftCenter: mask |= SPEAKER_FRONT_LEFT_OF_CENTER; break;
> +            case kAudioChannelLabel_RightCenter: mask |= SPEAKER_FRONT_RIGHT_OF_CENTER; break;
> +        }
> +    }
> +
> +    return mask;
> +}
> +
> +/* 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).  Here, we find the nearest configuration that Windows
> + * would report for a given channel layout. */
> +static void convert_channel_layout(const AudioChannelLayout *ca_layout, WAVEFORMATEXTENSIBLE *fmt)
> +{
> +    DWORD ca_mask = ca_channel_layout_to_channel_mask(ca_layout);
> +
> +    TRACE("Got channel mask for CA: 0x%x\n", ca_mask);
> +
> +    if (ca_layout->mNumberChannelDescriptions == 1)
> +    {
> +        fmt->Format.nChannels = 1;
> +        fmt->dwChannelMask = ca_mask;
> +        return;
> +    }
> +
> +    /* compare against known configurations and find smallest configuration
> +     * which is a superset of the given speakers */
> +
> +    if (ca_layout->mNumberChannelDescriptions <= 2 &&
> +            (ca_mask & ~KSAUDIO_SPEAKER_STEREO) == 0)
> +    {
> +        fmt->Format.nChannels = 2;
> +        fmt->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
> +        return;
> +    }
> +
> +    if (ca_layout->mNumberChannelDescriptions <= 4 &&
> +            (ca_mask & ~KSAUDIO_SPEAKER_QUAD) == 0)
> +    {
> +        fmt->Format.nChannels = 4;
> +        fmt->dwChannelMask = KSAUDIO_SPEAKER_QUAD;
> +        return;
> +    }
> +
> +    if (ca_layout->mNumberChannelDescriptions <= 4 &&
> +            (ca_mask & ~KSAUDIO_SPEAKER_SURROUND) == 0)
> +    {
> +        fmt->Format.nChannels = 4;
> +        fmt->dwChannelMask = KSAUDIO_SPEAKER_SURROUND;
> +        return;
> +    }
> +
> +    if (ca_layout->mNumberChannelDescriptions <= 6 &&
> +            (ca_mask & ~KSAUDIO_SPEAKER_5POINT1) == 0)
> +    {
> +        fmt->Format.nChannels = 6;
> +        fmt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
> +        return;
> +    }
> +
> +    if (ca_layout->mNumberChannelDescriptions <= 6 &&
> +            (ca_mask & ~KSAUDIO_SPEAKER_5POINT1_SURROUND) == 0)
> +    {
> +        fmt->Format.nChannels = 6;
> +        fmt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1_SURROUND;
> +        return;
> +    }
> +
> +    if (ca_layout->mNumberChannelDescriptions <= 8 &&
> +            (ca_mask & ~KSAUDIO_SPEAKER_7POINT1) == 0)
> +    {
> +        fmt->Format.nChannels = 8;
> +        fmt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1;
> +        return;
> +    }
> +
> +    if (ca_layout->mNumberChannelDescriptions <= 8 &&
> +            (ca_mask & ~KSAUDIO_SPEAKER_7POINT1_SURROUND) == 0)
> +    {
> +        fmt->Format.nChannels = 8;
> +        fmt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1_SURROUND;
> +        return;
> +    }
> +
> +    /* oddball format, report truthfully */
> +    fmt->Format.nChannels = ca_layout->mNumberChannelDescriptions;
> +    fmt->dwChannelMask = ca_mask;
> +}
> +
> +static DWORD get_channel_mask(unsigned int channels)
> +{
> +    switch(channels){
> +    case 0:
> +        return 0;
> +    case 1:
> +        return KSAUDIO_SPEAKER_MONO;
> +    case 2:
> +        return KSAUDIO_SPEAKER_STEREO;
> +    case 3:
> +        return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
> +    case 4:
> +        return KSAUDIO_SPEAKER_QUAD;    /* not _SURROUND */
> +    case 5:
> +        return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
> +    case 6:
> +        return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
> +    case 7:
> +        return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
> +    case 8:
> +        return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
> +    }
> +    FIXME("Unknown speaker configuration: %u\n", channels);
> +    return 0;
> +}
> +
> +static NTSTATUS get_mix_format(void *args)
> +{
> +    struct get_mix_format_params *params = args;
> +    AudioObjectPropertyAddress addr;
> +    AudioChannelLayout *layout;
> +    AudioBufferList *buffers;
> +    Float64 rate;
> +    UInt32 size;
> +    OSStatus sc;
> +    int i;
> +
> +    params->fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
> +
> +    addr.mScope = get_scope(params->flow);
> +    addr.mElement = 0;
> +    addr.mSelector = kAudioDevicePropertyPreferredChannelLayout;
> +
> +    sc = AudioObjectGetPropertyDataSize(params->dev_id, &addr, 0, NULL, &size);
> +    if(sc == noErr){
> +        layout = malloc(size);
> +        sc = AudioObjectGetPropertyData(params->dev_id, &addr, 0, NULL, &size, layout);
> +        if(sc == noErr){
> +            TRACE("Got channel layout: {tag: 0x%x, bitmap: 0x%x, num_descs: %u}\n",
> +                  (unsigned int)layout->mChannelLayoutTag, (unsigned int)layout->mChannelBitmap,
> +                  (unsigned int)layout->mNumberChannelDescriptions);
> +
> +            if(layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions){
> +                convert_channel_layout(layout, params->fmt);
> +            }else{
> +                WARN("Haven't implemented support for this layout tag: 0x%x, guessing at layout\n",
> +                     (unsigned int)layout->mChannelLayoutTag);
> +                params->fmt->Format.nChannels = 0;
> +            }
> +        }else{
> +            TRACE("Unable to get _PreferredChannelLayout property: %x, guessing at layout\n", (int)sc);
> +            params->fmt->Format.nChannels = 0;
> +        }
> +
> +        free(layout);
> +    }else{
> +        TRACE("Unable to get size for _PreferredChannelLayout property: %x, guessing at layout\n", (int)sc);
> +        params->fmt->Format.nChannels = 0;
> +    }
> +
> +    if(params->fmt->Format.nChannels == 0){
> +        addr.mScope = get_scope(params->flow);
> +        addr.mElement = 0;
> +        addr.mSelector = kAudioDevicePropertyStreamConfiguration;
> +
> +        sc = AudioObjectGetPropertyDataSize(params->dev_id, &addr, 0, NULL, &size);
> +        if(sc != noErr){
> +            WARN("Unable to get size for _StreamConfiguration property: %x\n", (int)sc);
> +            params->result = osstatus_to_hresult(sc);
> +            return STATUS_SUCCESS;
> +        }
> +
> +        buffers = malloc(size);
> +        if(!buffers){
> +            params->result = E_OUTOFMEMORY;
> +            return STATUS_SUCCESS;
> +        }
> +
> +        sc = AudioObjectGetPropertyData(params->dev_id, &addr, 0, NULL, &size, buffers);
> +        if(sc != noErr){
> +            free(buffers);
> +            WARN("Unable to get _StreamConfiguration property: %x\n", (int)sc);
> +            params->result = osstatus_to_hresult(sc);
> +            return STATUS_SUCCESS;
> +        }
> +
> +        for(i = 0; i < buffers->mNumberBuffers; ++i)
> +            params->fmt->Format.nChannels += buffers->mBuffers[i].mNumberChannels;
> +
> +        free(buffers);
> +
> +        params->fmt->dwChannelMask = get_channel_mask(params->fmt->Format.nChannels);
> +    }
> +
> +    addr.mSelector = kAudioDevicePropertyNominalSampleRate;
> +    size = sizeof(Float64);
> +    sc = AudioObjectGetPropertyData(params->dev_id, &addr, 0, NULL, &size, &rate);
> +    if(sc != noErr){
> +        WARN("Unable to get _NominalSampleRate property: %x\n", (int)sc);
> +        params->result = osstatus_to_hresult(sc);
> +        return STATUS_SUCCESS;
> +    }
> +    params->fmt->Format.nSamplesPerSec = rate;
> +
> +    params->fmt->Format.wBitsPerSample = 32;
> +    params->fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
> +
> +    params->fmt->Format.nBlockAlign = (params->fmt->Format.wBitsPerSample *
> +                                       params->fmt->Format.nChannels) / 8;
> +    params->fmt->Format.nAvgBytesPerSec = params->fmt->Format.nSamplesPerSec *
> +        params->fmt->Format.nBlockAlign;
> +
> +    params->fmt->Samples.wValidBitsPerSample = params->fmt->Format.wBitsPerSample;
> +    params->fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
> +    params->result = S_OK;
> +    return STATUS_SUCCESS;
> +}
> +
>  unixlib_entry_t __wine_unix_call_funcs[] =
>  {
>      get_endpoint_ids,
>      create_stream,
>      release_stream,
> +    get_mix_format,
>  };
> diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
> index 572126562c6..7ec282c514d 100644
> --- a/dlls/winecoreaudio.drv/mmdevdrv.c
> +++ b/dlls/winecoreaudio.drv/mmdevdrv.c
> @@ -689,32 +689,6 @@ static void dump_fmt(const WAVEFORMATEX *fmt)
>      }
>  }
>  
> -static DWORD get_channel_mask(unsigned int channels)
> -{
> -    switch(channels){
> -    case 0:
> -        return 0;
> -    case 1:
> -        return KSAUDIO_SPEAKER_MONO;
> -    case 2:
> -        return KSAUDIO_SPEAKER_STEREO;
> -    case 3:
> -        return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
> -    case 4:
> -        return KSAUDIO_SPEAKER_QUAD;    /* not _SURROUND */
> -    case 5:
> -        return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
> -    case 6:
> -        return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
> -    case 7:
> -        return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
> -    case 8:
> -        return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
> -    }
> -    FIXME("Unknown speaker configuration: %u\n", channels);
> -    return 0;
> -}
> -
>  static HRESULT ca_get_audiodesc(AudioStreamBasicDescription *desc,
>          const WAVEFORMATEX *fmt)
>  {
> @@ -1395,134 +1369,11 @@ unsupported:
>      return AUDCLNT_E_UNSUPPORTED_FORMAT;
>  }
>  
> -static DWORD ca_channel_layout_to_channel_mask(const AudioChannelLayout *layout)
> -{
> -    int i;
> -    DWORD mask = 0;
> -
> -    for (i = 0; i < layout->mNumberChannelDescriptions; ++i) {
> -        switch (layout->mChannelDescriptions[i].mChannelLabel) {
> -            default: FIXME("Unhandled channel 0x%x\n", (unsigned int)layout->mChannelDescriptions[i].mChannelLabel); break;
> -            case kAudioChannelLabel_Left: mask |= SPEAKER_FRONT_LEFT; break;
> -            case kAudioChannelLabel_Mono:
> -            case kAudioChannelLabel_Center: mask |= SPEAKER_FRONT_CENTER; break;
> -            case kAudioChannelLabel_Right: mask |= SPEAKER_FRONT_RIGHT; break;
> -            case kAudioChannelLabel_LeftSurround: mask |= SPEAKER_BACK_LEFT; break;
> -            case kAudioChannelLabel_CenterSurround: mask |= SPEAKER_BACK_CENTER; break;
> -            case kAudioChannelLabel_RightSurround: mask |= SPEAKER_BACK_RIGHT; break;
> -            case kAudioChannelLabel_LFEScreen: mask |= SPEAKER_LOW_FREQUENCY; break;
> -            case kAudioChannelLabel_LeftSurroundDirect: mask |= SPEAKER_SIDE_LEFT; break;
> -            case kAudioChannelLabel_RightSurroundDirect: mask |= SPEAKER_SIDE_RIGHT; break;
> -            case kAudioChannelLabel_TopCenterSurround: mask |= SPEAKER_TOP_CENTER; break;
> -            case kAudioChannelLabel_VerticalHeightLeft: mask |= SPEAKER_TOP_FRONT_LEFT; break;
> -            case kAudioChannelLabel_VerticalHeightCenter: mask |= SPEAKER_TOP_FRONT_CENTER; break;
> -            case kAudioChannelLabel_VerticalHeightRight: mask |= SPEAKER_TOP_FRONT_RIGHT; break;
> -            case kAudioChannelLabel_TopBackLeft: mask |= SPEAKER_TOP_BACK_LEFT; break;
> -            case kAudioChannelLabel_TopBackCenter: mask |= SPEAKER_TOP_BACK_CENTER; break;
> -            case kAudioChannelLabel_TopBackRight: mask |= SPEAKER_TOP_BACK_RIGHT; break;
> -            case kAudioChannelLabel_LeftCenter: mask |= SPEAKER_FRONT_LEFT_OF_CENTER; break;
> -            case kAudioChannelLabel_RightCenter: mask |= SPEAKER_FRONT_RIGHT_OF_CENTER; break;
> -        }
> -    }
> -
> -    return mask;
> -}
> -
> -/* 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).  Here, we find the nearest configuration that Windows
> - * would report for a given channel layout. */
> -static void convert_channel_layout(const AudioChannelLayout *ca_layout, WAVEFORMATEXTENSIBLE *fmt)
> -{
> -    DWORD ca_mask = ca_channel_layout_to_channel_mask(ca_layout);
> -
> -    TRACE("Got channel mask for CA: 0x%x\n", ca_mask);
> -
> -    if (ca_layout->mNumberChannelDescriptions == 1)
> -    {
> -        fmt->Format.nChannels = 1;
> -        fmt->dwChannelMask = ca_mask;
> -        return;
> -    }
> -
> -    /* compare against known configurations and find smallest configuration
> -     * which is a superset of the given speakers */
> -
> -    if (ca_layout->mNumberChannelDescriptions <= 2 &&
> -            (ca_mask & ~KSAUDIO_SPEAKER_STEREO) == 0)
> -    {
> -        fmt->Format.nChannels = 2;
> -        fmt->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
> -        return;
> -    }
> -
> -    if (ca_layout->mNumberChannelDescriptions <= 4 &&
> -            (ca_mask & ~KSAUDIO_SPEAKER_QUAD) == 0)
> -    {
> -        fmt->Format.nChannels = 4;
> -        fmt->dwChannelMask = KSAUDIO_SPEAKER_QUAD;
> -        return;
> -    }
> -
> -    if (ca_layout->mNumberChannelDescriptions <= 4 &&
> -            (ca_mask & ~KSAUDIO_SPEAKER_SURROUND) == 0)
> -    {
> -        fmt->Format.nChannels = 4;
> -        fmt->dwChannelMask = KSAUDIO_SPEAKER_SURROUND;
> -        return;
> -    }
> -
> -    if (ca_layout->mNumberChannelDescriptions <= 6 &&
> -            (ca_mask & ~KSAUDIO_SPEAKER_5POINT1) == 0)
> -    {
> -        fmt->Format.nChannels = 6;
> -        fmt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1;
> -        return;
> -    }
> -
> -    if (ca_layout->mNumberChannelDescriptions <= 6 &&
> -            (ca_mask & ~KSAUDIO_SPEAKER_5POINT1_SURROUND) == 0)
> -    {
> -        fmt->Format.nChannels = 6;
> -        fmt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1_SURROUND;
> -        return;
> -    }
> -
> -    if (ca_layout->mNumberChannelDescriptions <= 8 &&
> -            (ca_mask & ~KSAUDIO_SPEAKER_7POINT1) == 0)
> -    {
> -        fmt->Format.nChannels = 8;
> -        fmt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1;
> -        return;
> -    }
> -
> -    if (ca_layout->mNumberChannelDescriptions <= 8 &&
> -            (ca_mask & ~KSAUDIO_SPEAKER_7POINT1_SURROUND) == 0)
> -    {
> -        fmt->Format.nChannels = 8;
> -        fmt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1_SURROUND;
> -        return;
> -    }
> -
> -    /* oddball format, report truthfully */
> -    fmt->Format.nChannels = ca_layout->mNumberChannelDescriptions;
> -    fmt->dwChannelMask = ca_mask;
> -}
> -
>  static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface,
>          WAVEFORMATEX **pwfx)
>  {
>      ACImpl *This = impl_from_IAudioClient3(iface);
> -    WAVEFORMATEXTENSIBLE *fmt;
> -    OSStatus sc;
> -    UInt32 size;
> -    Float64 rate;
> -    AudioBufferList *buffers;
> -    AudioChannelLayout *layout;
> -    AudioObjectPropertyAddress addr;
> -    int i;
> +    struct get_mix_format_params params;
>  
>      TRACE("(%p)->(%p)\n", This, pwfx);
>  
> @@ -1530,104 +1381,21 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface,
>          return E_POINTER;
>      *pwfx = NULL;
>  
> -    fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE));
> -    if(!fmt)
> +    params.dev_id = This->adevid;
> +    params.flow = This->dataflow;
> +    params.fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE));
> +    if(!params.fmt)
>          return E_OUTOFMEMORY;
>  
> -    fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
> -
> -    addr.mScope = This->scope;
> -    addr.mElement = 0;
> -    addr.mSelector = kAudioDevicePropertyPreferredChannelLayout;
> -
> -    sc = AudioObjectGetPropertyDataSize(This->adevid, &addr, 0, NULL, &size);
> -    if(sc == noErr){
> -        layout = HeapAlloc(GetProcessHeap(), 0, size);
> -
> -        sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL, &size, layout);
> -        if(sc == noErr){
> -            TRACE("Got channel layout: {tag: 0x%x, bitmap: 0x%x, num_descs: %u}\n",
> -                  (unsigned int)layout->mChannelLayoutTag, (unsigned int)layout->mChannelBitmap,
> -                  (unsigned int)layout->mNumberChannelDescriptions);
> -
> -            if(layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions){
> -                convert_channel_layout(layout, fmt);
> -            }else{
> -                WARN("Haven't implemented support for this layout tag: 0x%x, guessing at layout\n", (unsigned int)layout->mChannelLayoutTag);
> -                fmt->Format.nChannels = 0;
> -            }
> -        }else{
> -            TRACE("Unable to get _PreferredChannelLayout property: %x, guessing at layout\n", (int)sc);
> -            fmt->Format.nChannels = 0;
> -        }
> -
> -        HeapFree(GetProcessHeap(), 0, layout);
> -    }else{
> -        TRACE("Unable to get size for _PreferredChannelLayout property: %x, guessing at layout\n", (int)sc);
> -        fmt->Format.nChannels = 0;
> -    }
> -
> -    if(fmt->Format.nChannels == 0){
> -        addr.mScope = This->scope;
> -        addr.mElement = 0;
> -        addr.mSelector = kAudioDevicePropertyStreamConfiguration;
> -
> -        sc = AudioObjectGetPropertyDataSize(This->adevid, &addr, 0, NULL, &size);
> -        if(sc != noErr){
> -            CoTaskMemFree(fmt);
> -            WARN("Unable to get size for _StreamConfiguration property: %x\n", (int)sc);
> -            return osstatus_to_hresult(sc);
> -        }
> -
> -        buffers = HeapAlloc(GetProcessHeap(), 0, size);
> -        if(!buffers){
> -            CoTaskMemFree(fmt);
> -            return E_OUTOFMEMORY;
> -        }
> -
> -        sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL,
> -                &size, buffers);
> -        if(sc != noErr){
> -            CoTaskMemFree(fmt);
> -            HeapFree(GetProcessHeap(), 0, buffers);
> -            WARN("Unable to get _StreamConfiguration property: %x\n", (int)sc);
> -            return osstatus_to_hresult(sc);
> -        }
> -
> -        fmt->Format.nChannels = 0;
> -        for(i = 0; i < buffers->mNumberBuffers; ++i)
> -            fmt->Format.nChannels += buffers->mBuffers[i].mNumberChannels;
> -
> -        HeapFree(GetProcessHeap(), 0, buffers);
> -
> -        fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels);
> -    }
> +    UNIX_CALL(get_mix_format, &params);
>  
> -    addr.mSelector = kAudioDevicePropertyNominalSampleRate;
> -    size = sizeof(Float64);
> -    sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL, &size, &rate);
> -    if(sc != noErr){
> -        CoTaskMemFree(fmt);
> -        WARN("Unable to get _NominalSampleRate property: %x\n", (int)sc);
> -        return osstatus_to_hresult(sc);
> -    }
> -    fmt->Format.nSamplesPerSec = rate;
> -
> -    fmt->Format.wBitsPerSample = 32;
> -    fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
> -
> -    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);
> +    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/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h
> index 7ebdc0b7786..e247b789d55 100644
> --- a/dlls/winecoreaudio.drv/unixlib.h
> +++ b/dlls/winecoreaudio.drv/unixlib.h
> @@ -75,11 +75,20 @@ struct release_stream_params
>      HRESULT result;
>  };
>  
> +struct get_mix_format_params
> +{
> +    EDataFlow flow;
> +    DWORD dev_id;
> +    WAVEFORMATEXTENSIBLE *fmt;
> +    HRESULT result;
> +};
> +
>  enum unix_funcs
>  {
>      unix_get_endpoint_ids,
>      unix_create_stream,
>      unix_release_stream,
> +    unix_get_mix_format,
>  };
>  
>  extern unixlib_handle_t coreaudio_handle;
> -- 
> 2.23.0
> 
> 



More information about the wine-devel mailing list