[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, ¶ms);
- 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 = ¶ms.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