Signed-off-by: Huw Davies huw@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, ¶ms);
- 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 = ¶ms.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;
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Thu, Nov 18, 2021 at 07:52:38AM +0000, Huw Davies wrote:
Signed-off-by: Huw Davies huw@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, ¶ms);
- 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 = ¶ms.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