mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added patch to implement GetPropValue function in winepulse
This commit is contained in:
parent
7bcb2e7adb
commit
ca0d3d1dca
@ -0,0 +1,190 @@
|
||||
From b6c4b15d71542a567f6ca67fe4d0463b04c5fedc Mon Sep 17 00:00:00 2001
|
||||
From: Mark Harmstone <mark@harmstone.com>
|
||||
Date: Thu, 4 Dec 2014 21:36:42 +0000
|
||||
Subject: [PATCH] winepulse: implement GetPropValue
|
||||
|
||||
---
|
||||
dlls/winepulse.drv/mmdevdrv.c | 153 ++++++++++++++++++++++++++++++++++
|
||||
dlls/winepulse.drv/winepulse.drv.spec | 1 +
|
||||
2 files changed, 154 insertions(+)
|
||||
|
||||
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
||||
index 37ff7ee..3acbca5 100644
|
||||
--- a/dlls/winepulse.drv/mmdevdrv.c
|
||||
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "initguid.h"
|
||||
#include "ks.h"
|
||||
#include "ksmedia.h"
|
||||
+#include "propkey.h"
|
||||
#include "mmdeviceapi.h"
|
||||
#include "audioclient.h"
|
||||
#include "endpointvolume.h"
|
||||
@@ -3430,3 +3431,155 @@ HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
|
||||
*out = &This->IAudioSessionManager2_iface;
|
||||
return S_OK;
|
||||
}
|
||||
+
|
||||
+enum AudioDeviceConnectionType {
|
||||
+ AudioDeviceConnectionType_Unknown = 0,
|
||||
+ AudioDeviceConnectionType_PCI,
|
||||
+ AudioDeviceConnectionType_USB
|
||||
+};
|
||||
+
|
||||
+static HRESULT pulse_set_device_path(pa_proplist *p, int index, GUID *guid, PROPVARIANT *pv)
|
||||
+{
|
||||
+ const char *buffer;
|
||||
+ enum AudioDeviceConnectionType connection;
|
||||
+ USHORT vendor_id, product_id;
|
||||
+ UINT serial_number;
|
||||
+
|
||||
+ static const WCHAR usbformatW[] = { '{','1','}','.','U','S','B','\\','V','I','D','_',
|
||||
+ '%','0','4','X','&','P','I','D','_','%','0','4','X','\\',
|
||||
+ '%','u','&','%','0','8','X',0 }; /* "{1}.USB\VID_%04X&PID_%04X\%u&%08X" */
|
||||
+ static const WCHAR pciformatW[] = { '{','1','}','.','H','D','A','U','D','I','O','\\','F','U','N','C','_','0','1','&',
|
||||
+ 'V','E','N','_','%','0','4','X','&','D','E','V','_',
|
||||
+ '%','0','4','X','\\','%','u','&','%','0','8','X',0 }; /* "{1}.HDAUDIO\FUNC_01&VEN_%04X&DEV_%04X\%u&%08X" */
|
||||
+
|
||||
+ buffer = pa_proplist_gets(p, PA_PROP_DEVICE_BUS);
|
||||
+
|
||||
+ connection = AudioDeviceConnectionType_Unknown;
|
||||
+ if (buffer) {
|
||||
+ if (!strcmp(buffer,"pci"))
|
||||
+ connection = AudioDeviceConnectionType_PCI;
|
||||
+ else if (!strcmp(buffer,"usb"))
|
||||
+ connection = AudioDeviceConnectionType_USB;
|
||||
+ }
|
||||
+
|
||||
+ if (connection == AudioDeviceConnectionType_Unknown)
|
||||
+ return E_FAIL;
|
||||
+
|
||||
+ buffer = pa_proplist_gets(p, PA_PROP_DEVICE_VENDOR_ID);
|
||||
+ if (buffer)
|
||||
+ vendor_id = strtol(buffer, NULL, 16);
|
||||
+ else
|
||||
+ return E_FAIL;
|
||||
+
|
||||
+ buffer = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_ID);
|
||||
+ if (buffer)
|
||||
+ product_id = strtol(buffer, NULL, 16);
|
||||
+ else
|
||||
+ return E_FAIL;
|
||||
+
|
||||
+ /* As hardly any audio devices have serial numbers, Windows instead
|
||||
+ appears to use a persistent random number. We emulate this here
|
||||
+ by instead using the last 8 hex digits of the GUID. */
|
||||
+ serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7];
|
||||
+
|
||||
+ pv->vt = VT_LPWSTR;
|
||||
+ pv->u.pwszVal = CoTaskMemAlloc(128 * sizeof(WCHAR));
|
||||
+
|
||||
+ if (!pv->u.pwszVal)
|
||||
+ return E_OUTOFMEMORY;
|
||||
+
|
||||
+ if (connection == AudioDeviceConnectionType_USB)
|
||||
+ sprintfW( pv->u.pwszVal, usbformatW, vendor_id, product_id, index, serial_number);
|
||||
+ else if (connection == AudioDeviceConnectionType_PCI)
|
||||
+ sprintfW( pv->u.pwszVal, pciformatW, vendor_id, product_id, index, serial_number);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+typedef struct {
|
||||
+ const PROPERTYKEY *prop;
|
||||
+ PROPVARIANT *pv;
|
||||
+ GUID *guid;
|
||||
+ HRESULT hr;
|
||||
+} pulse_prop_values_info_cb_data;
|
||||
+
|
||||
+static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
|
||||
+ {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
|
||||
+};
|
||||
+
|
||||
+static void pulse_prop_values_sink_info_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
|
||||
+{
|
||||
+ pulse_prop_values_info_cb_data *st = (pulse_prop_values_info_cb_data*)userdata;
|
||||
+
|
||||
+ if (!i)
|
||||
+ return;
|
||||
+
|
||||
+ if (IsEqualPropertyKey(*st->prop, devicepath_key))
|
||||
+ st->hr = pulse_set_device_path(i->proplist, i->index, st->guid, st->pv);
|
||||
+ else if (IsEqualPropertyKey(*st->prop, PKEY_AudioEndpoint_FormFactor)) {
|
||||
+ st->pv->vt = VT_UI4;
|
||||
+ st->pv->u.ulVal = Speakers;
|
||||
+
|
||||
+ st->hr = S_OK;
|
||||
+ } else
|
||||
+ st->hr = E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static void pulse_prop_values_source_info_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata)
|
||||
+{
|
||||
+ pulse_prop_values_info_cb_data *st = (pulse_prop_values_info_cb_data*)userdata;
|
||||
+
|
||||
+ if (!i)
|
||||
+ return;
|
||||
+
|
||||
+ if (IsEqualPropertyKey(*st->prop, devicepath_key)) {
|
||||
+ st->hr = pulse_set_device_path(i->proplist, i->index, st->guid, st->pv);
|
||||
+ } else if (IsEqualPropertyKey(*st->prop, PKEY_AudioEndpoint_FormFactor)) {
|
||||
+ st->pv->vt = VT_UI4;
|
||||
+ st->pv->u.ulVal = (i->monitor_of_sink == PA_INVALID_INDEX) ? Microphone : LineLevel;
|
||||
+
|
||||
+ st->hr = S_OK;
|
||||
+ } else
|
||||
+ st->hr = E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARIANT *out)
|
||||
+{
|
||||
+ char name[256];
|
||||
+ EDataFlow flow;
|
||||
+ pulse_prop_values_info_cb_data userdata;
|
||||
+ pa_operation *o;
|
||||
+
|
||||
+ TRACE("%s, (%s,%u), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out);
|
||||
+
|
||||
+ if (IsEqualGUID(guid, &pulse_render_guid) || IsEqualGUID(guid, &pulse_capture_guid))
|
||||
+ return E_NOTIMPL;
|
||||
+
|
||||
+ if (!get_pulse_name_by_guid(guid, name, sizeof(name), &flow)) {
|
||||
+ WARN("Unknown interface %s\n", debugstr_guid(guid));
|
||||
+ return E_NOINTERFACE;
|
||||
+ }
|
||||
+
|
||||
+ if (!IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_FormFactor) &&
|
||||
+ !IsEqualPropertyKey(*prop, devicepath_key)) {
|
||||
+ return E_NOTIMPL;
|
||||
+ }
|
||||
+
|
||||
+ userdata.prop = prop;
|
||||
+ userdata.pv = out;
|
||||
+ userdata.guid = guid;
|
||||
+ userdata.hr = E_FAIL;
|
||||
+
|
||||
+ if (flow == eRender)
|
||||
+ o = pa_context_get_sink_info_by_name(pulse_ctx, name, &pulse_prop_values_sink_info_cb, &userdata);
|
||||
+ else
|
||||
+ o = pa_context_get_source_info_by_name(pulse_ctx, name, &pulse_prop_values_source_info_cb, &userdata);
|
||||
+
|
||||
+ if (!o)
|
||||
+ return E_FAIL;
|
||||
+
|
||||
+ while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { }
|
||||
+ pa_operation_unref(o);
|
||||
+
|
||||
+ return userdata.hr;
|
||||
+}
|
||||
diff --git a/dlls/winepulse.drv/winepulse.drv.spec b/dlls/winepulse.drv/winepulse.drv.spec
|
||||
index 612bf46..adda949 100644
|
||||
--- a/dlls/winepulse.drv/winepulse.drv.spec
|
||||
+++ b/dlls/winepulse.drv/winepulse.drv.spec
|
||||
@@ -3,3 +3,4 @@
|
||||
@ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs
|
||||
@ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint
|
||||
@ stdcall -private GetAudioSessionManager(ptr ptr) AUDDRV_GetAudioSessionManager
|
||||
+@ stdcall -private GetPropValue(ptr ptr ptr) AUDDRV_GetPropValue
|
||||
--
|
||||
2.0.4
|
||||
|
@ -2,3 +2,4 @@ Fixes: [10495] Support for PulseAudio backend for audio
|
||||
Fixes: Allow selection of audio device for PulseAudio backend
|
||||
Fixes: [37042] Implement exclusive mode in PulseAudio backend
|
||||
Fixes: Fix possible segfault in pulse_rd_loop of PulseAudio backend
|
||||
Fixes: Implement function GetPropValue
|
||||
|
Loading…
x
Reference in New Issue
Block a user