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

Huw Davies huw at codeweavers.com
Tue Nov 23 01:54:58 CST 2021


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