From: Claire Girka claire@sitedethib.com
When GetMixFormat is used, return values specific to the selected device instead of those of the default one. This is especially useful when the default audio device features less channels than one specifically selected by the application. --- dlls/winepulse.drv/mmdevdrv.c | 16 +++++++++++++++- dlls/winepulse.drv/pulse.c | 21 +++++++++++++++++++++ dlls/winepulse.drv/unixlib.h | 9 +++++++++ 3 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 3cbbc1d8115..fca36b22d90 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -1136,13 +1136,27 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface, WAVEFORMATEX **pwfx) { ACImpl *This = impl_from_IAudioClient3(iface); + const WAVEFORMATEX *fmt;
TRACE("(%p)->(%p)\n", This, pwfx);
if (!pwfx) return E_POINTER;
- *pwfx = clone_format(&pulse_config.modes[This->dataflow == eCapture].format.Format); + fmt = &pulse_config.modes[This->dataflow == eCapture].format.Format; + + if (This->pulse_name[0]) { + struct get_device_mix_format_params params; + params.render = This->dataflow == eRender; + params.pulse_name = This->pulse_name; + pulse_call(get_device_mix_format, ¶ms); + + if (SUCCEEDED(params.result)) + fmt = ¶ms.fmt.Format; + } + + *pwfx = clone_format(fmt); + if (!*pwfx) return E_OUTOFMEMORY; dump_fmt(*pwfx); diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 1701b9c281c..1855ffe11f4 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -739,6 +739,26 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt, REFERENC fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; }
+static NTSTATUS pulse_get_device_mix_format(void *args) +{ + struct get_device_mix_format_params *params = args; + struct list *list = params->render ? &g_phys_speakers : &g_phys_sources; + PhysDevice *dev; + + LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) { + if (strcmp(params->pulse_name, dev->pulse_name)) + continue; + + params->fmt = dev->fmt; + params->result = S_OK; + + return STATUS_SUCCESS; + } + + params->result = E_FAIL; + return STATUS_SUCCESS; +} + /* some poorly-behaved applications call audio functions during DllMain, so we * have to do as much as possible without creating a new thread. this function * sets up a synchronous connection to verify the server is running and query @@ -2316,6 +2336,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = pulse_test_connect, pulse_is_started, pulse_get_prop_value, + pulse_get_device_mix_format, };
#ifdef _WIN64 diff --git a/dlls/winepulse.drv/unixlib.h b/dlls/winepulse.drv/unixlib.h index f224f26c909..6f8e3cf3211 100644 --- a/dlls/winepulse.drv/unixlib.h +++ b/dlls/winepulse.drv/unixlib.h @@ -159,6 +159,14 @@ struct get_current_padding_params UINT32 *padding; };
+struct get_device_mix_format_params +{ + const char *pulse_name; + HRESULT result; + BOOL render; + WAVEFORMATEXTENSIBLE fmt; +}; + struct get_next_packet_size_params { stream_handle stream; @@ -252,4 +260,5 @@ enum unix_funcs test_connect, is_started, get_prop_value, + get_device_mix_format, };