From ca0d3d1dcae6b5c73485ac364755f8e33c0022dc Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Fri, 5 Dec 2014 15:54:37 +0000 Subject: [PATCH] Added patch to implement GetPropValue function in winepulse --- ...031-winepulse-implement-GetPropValue.patch | 190 ++++++++++++++++++ .../winepulse-PulseAudio_Support/definition | 1 + 2 files changed, 191 insertions(+) create mode 100644 patches/winepulse-PulseAudio_Support/0031-winepulse-implement-GetPropValue.patch diff --git a/patches/winepulse-PulseAudio_Support/0031-winepulse-implement-GetPropValue.patch b/patches/winepulse-PulseAudio_Support/0031-winepulse-implement-GetPropValue.patch new file mode 100644 index 00000000..ffc31cb2 --- /dev/null +++ b/patches/winepulse-PulseAudio_Support/0031-winepulse-implement-GetPropValue.patch @@ -0,0 +1,190 @@ +From b6c4b15d71542a567f6ca67fe4d0463b04c5fedc Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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 + diff --git a/patches/winepulse-PulseAudio_Support/definition b/patches/winepulse-PulseAudio_Support/definition index 9b6f6216..2bb7d5b0 100644 --- a/patches/winepulse-PulseAudio_Support/definition +++ b/patches/winepulse-PulseAudio_Support/definition @@ -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