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

Huw Davies huw at codeweavers.com
Thu Nov 18 01:52:38 CST 2021


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