From: Mark Harmstone Subject: [PATCH 1/2] mmdevapi: allow GetPropValue function in audio drivers Message-Id: <546B88FB.1040704@burntcomma.com> Date: Tue, 18 Nov 2014 17:59:23 +0000 This is a replacement for a rejected patch I sent a week or two ago, incorporating suggestions kindly made by Andrew Eikum. The first patch adds support for a new optional function in the audio drivers, GetPropValue, which allows them to return arbitrary mmdev properties. The two currently supported properties are the form factor and the device path. The second patch adds this function into winealsa and returns a fake device path incorporating the device's product and vendor ID. These patches are required by the Rocksmith games, which use these properties to identify the guitar cable. --- dlls/mmdevapi/devenum.c | 38 ++++++++++++++++++++++++++++++++++++++ dlls/mmdevapi/main.c | 3 +++ dlls/mmdevapi/mmdevapi.h | 2 ++ 3 files changed, 43 insertions(+) diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index e2a7cc5..a0ee958 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -264,6 +264,30 @@ static HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERT return hr; } +static HRESULT set_driver_prop_value(GUID *id, const EDataFlow flow, const PROPERTYKEY *prop) +{ + HRESULT hr; + PROPVARIANT pv; + + if (!drvs.pGetPropValue) + { + TRACE("Driver does not implement GetPropValue\n"); + return E_NOTIMPL; + } + + hr = drvs.pGetPropValue(id, prop, &pv); + + if (SUCCEEDED(hr)) + { + MMDevice_SetPropValue(id, flow, prop, &pv); + + if (pv.vt == VT_LPWSTR) + HeapFree(GetProcessHeap(), 0, pv.u.pwszVal); + } + + return hr; +} + /* Creates or updates the state of a device * If GUID is null, a random guid will be assigned * and the device will be created @@ -279,6 +303,10 @@ static MMDevice *MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD st {0x233164c8, 0x1b2c, 0x4c7d, {0xbc, 0x68, 0xb6, 0x71, 0x68, 0x7a, 0x25, 0x67}}, 1 }; + static const PROPERTYKEY devicepath_key = { + {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2 + }; + for (i = 0; i < MMDevice_count; ++i) { MMDevice *device = MMDevice_head[i]; @@ -338,6 +366,16 @@ static MMDevice *MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD st pv.u.pwszVal = guidstr; MMDevice_SetPropValue(id, flow, &deviceinterface_key, &pv); + set_driver_prop_value(id, flow, &devicepath_key); + + if (FAILED(set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_FormFactor))) + { + pv.vt = VT_UI4; + pv.u.ulVal = (flow == eCapture) ? Microphone : Speakers; + + MMDevice_SetPropValue(id, flow, &PKEY_AudioEndpoint_FormFactor, &pv); + } + RegCloseKey(keyprop); } RegCloseKey(key); diff --git a/dlls/mmdevapi/main.c b/dlls/mmdevapi/main.c index 447813f..52cf6f1 100644 --- a/dlls/mmdevapi/main.c +++ b/dlls/mmdevapi/main.c @@ -97,6 +97,9 @@ static BOOL load_driver(const WCHAR *name, DriverFuncs *driver) LDFC(GetAudioSessionManager); #undef LDFC + /* optional - do not fail if not found */ + driver->pGetPropValue = (void*)GetProcAddress(driver->module, "GetPropValue"); + driver->priority = driver->pGetPriority(); lstrcpyW(driver->module_name, driver_module); diff --git a/dlls/mmdevapi/mmdevapi.h b/dlls/mmdevapi/mmdevapi.h index 2a04780..2b40a05 100644 --- a/dlls/mmdevapi/mmdevapi.h +++ b/dlls/mmdevapi/mmdevapi.h @@ -54,6 +54,8 @@ typedef struct _DriverFuncs { IAudioClient **out); HRESULT (WINAPI *pGetAudioSessionManager)(IMMDevice *device, IAudioSessionManager2 **out); + HRESULT (WINAPI *pGetPropValue)(GUID *guid, + const PROPERTYKEY *prop, PROPVARIANT *out); } DriverFuncs; extern DriverFuncs drvs DECLSPEC_HIDDEN;