[PATCH v3 2/2] winepulse: Return device-specific values for GetMixFormat and GetDevicePeriod

Claire Girka wine at gitlab.winehq.org
Wed Jun 29 10:28:34 CDT 2022


From: Claire Girka <claire at sitedethib.com>

When GetMixFormat or GetDevicePeriod 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 | 32 +++++++++++++++++++++++++++++++-
 dlls/winepulse.drv/pulse.c    | 23 +++++++++++++++++++++++
 dlls/winepulse.drv/unixlib.h  | 11 +++++++++++
 3 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index 3cbbc1d8115..a300ec517c4 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_settings_params params;
+        params.render = This->dataflow == eRender;
+        params.pulse_name = This->pulse_name;
+        pulse_call(get_device_settings, &params);
+
+        if (SUCCEEDED(params.result))
+            fmt = &params.fmt.Format;
+    }
+
+    *pwfx = clone_format(fmt);
+
     if (!*pwfx)
         return E_OUTOFMEMORY;
     dump_fmt(*pwfx);
@@ -1159,6 +1173,22 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface,
     if (!defperiod && !minperiod)
         return E_POINTER;
 
+    if (This->pulse_name[0]) {
+        struct get_device_settings_params params;
+        params.render = This->dataflow == eRender;
+        params.pulse_name = This->pulse_name;
+        pulse_call(get_device_settings, &params);
+
+        if (SUCCEEDED(params.result)) {
+            if (defperiod)
+                *defperiod = params.def_period;
+            if (minperiod)
+                *minperiod = params.min_period;
+
+            return S_OK;
+        }
+    }
+
     if (defperiod)
         *defperiod = pulse_config.modes[This->dataflow == eCapture].def_period;
     if (minperiod)
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
index 1701b9c281c..4e7703c4128 100644
--- a/dlls/winepulse.drv/pulse.c
+++ b/dlls/winepulse.drv/pulse.c
@@ -739,6 +739,28 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt, REFERENC
         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
 }
 
+static NTSTATUS pulse_get_device_settings(void *args)
+{
+    struct get_device_settings_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->def_period = dev->def_period;
+        params->min_period = dev->min_period;
+        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 +2338,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
     pulse_test_connect,
     pulse_is_started,
     pulse_get_prop_value,
+    pulse_get_device_settings,
 };
 
 #ifdef _WIN64
diff --git a/dlls/winepulse.drv/unixlib.h b/dlls/winepulse.drv/unixlib.h
index f224f26c909..0c340e601d6 100644
--- a/dlls/winepulse.drv/unixlib.h
+++ b/dlls/winepulse.drv/unixlib.h
@@ -159,6 +159,16 @@ struct get_current_padding_params
     UINT32 *padding;
 };
 
+struct get_device_settings_params
+{
+    const char *pulse_name;
+    HRESULT result;
+    BOOL render;
+    WAVEFORMATEXTENSIBLE fmt;
+    REFERENCE_TIME def_period;
+    REFERENCE_TIME min_period;
+};
+
 struct get_next_packet_size_params
 {
     stream_handle stream;
@@ -252,4 +262,5 @@ enum unix_funcs
     test_connect,
     is_started,
     get_prop_value,
+    get_device_settings,
 };
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/337



More information about the wine-devel mailing list