From acccdce4c45d9e8db8f21deb2e4d764ad21edb9c Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Sat, 27 Dec 2014 21:34:48 +0000 Subject: [PATCH] winealsa: Return PKEY_AudioEndpoint_PhysicalSpeakers device prop. --- dlls/mmdevapi/devenum.c | 3 ++ dlls/winealsa.drv/mmdevdrv.c | 84 ++++++++++++++++++++++++++++++++---- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index 56f770a4547..c1404371768 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -371,6 +371,9 @@ static MMDevice *MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD st MMDevice_SetPropValue(id, flow, &PKEY_AudioEndpoint_FormFactor, &pv); } + if (flow != eCapture) + set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_PhysicalSpeakers); + RegCloseKey(keyprop); } RegCloseKey(key); diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index 8f93e7950fa..d2fb2d37872 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -32,7 +32,10 @@ #include "wine/unicode.h" #include "wine/list.h" +#include "propsys.h" +#include "initguid.h" #include "ole2.h" +#include "propkey.h" #include "mmdeviceapi.h" #include "devpkey.h" #include "mmsystem.h" @@ -3912,6 +3915,44 @@ HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device, return S_OK; } +static unsigned int alsa_probe_num_speakers(char *name) { + snd_pcm_t *handle; + snd_pcm_hw_params_t *params; + int err; + unsigned int max_channels = 0; + + if ((err = snd_pcm_open(&handle, name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { + WARN("The device \"%s\" failed to open: %d (%s).\n", + name, err, snd_strerror(err)); + return 0; + } + + params = HeapAlloc(GetProcessHeap(), 0, snd_pcm_hw_params_sizeof()); + if (!params) { + WARN("Out of memory.\n"); + snd_pcm_close(handle); + return 0; + } + + if ((err = snd_pcm_hw_params_any(handle, params)) < 0) { + WARN("snd_pcm_hw_params_any failed for \"%s\": %d (%s).\n", + name, err, snd_strerror(err)); + goto exit; + } + + if ((err = snd_pcm_hw_params_get_channels_max(params, + &max_channels)) < 0){ + WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err)); + goto exit; + } + +exit: + HeapFree(GetProcessHeap(), 0, params); + snd_pcm_close(handle); + + return max_channels; +} + enum AudioDeviceConnectionType { AudioDeviceConnectionType_Unknown = 0, AudioDeviceConnectionType_PCI, @@ -3920,25 +3961,27 @@ enum AudioDeviceConnectionType { HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARIANT *out) { + char name[256]; + EDataFlow flow; + static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */ {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2 }; TRACE("%s, (%s,%u), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out); + if(!get_alsa_name_by_guid(guid, name, sizeof(name), &flow)) + { + WARN("Unknown interface %s\n", debugstr_guid(guid)); + return E_NOINTERFACE; + } + if(IsEqualPropertyKey(*prop, devicepath_key)) { - char name[256], uevent[MAX_PATH]; - EDataFlow flow; + char uevent[MAX_PATH]; FILE *fuevent; int card, device; - if(!get_alsa_name_by_guid(guid, name, sizeof(name), &flow)) - { - WARN("Unknown interface %s\n", debugstr_guid(guid)); - return E_NOINTERFACE; - } - /* only implemented for identifiable devices, i.e. not "default" */ if(!sscanf(name, "plughw:%u,%u", &card, &device)) return E_NOTIMPL; @@ -4013,6 +4056,31 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI WARN("Could not open %s for reading\n", uevent); return E_NOTIMPL; } + } else if (flow != eCapture && IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) { + unsigned int num_speakers, card, device; + char hwname[255]; + + if (sscanf(name, "plughw:%u,%u", &card, &device)) + sprintf(hwname, "hw:%u,%u", card, device); /* must be hw rather than plughw to work */ + else + strcpy(hwname, name); + + num_speakers = alsa_probe_num_speakers(hwname); + if (num_speakers == 0) + return E_FAIL; + + out->vt = VT_UI4; + + if (num_speakers >= 6) + out->u.ulVal = KSAUDIO_SPEAKER_5POINT1; + else if (num_speakers >= 4) + out->u.ulVal = KSAUDIO_SPEAKER_QUAD; + else if (num_speakers >= 2) + out->u.ulVal = KSAUDIO_SPEAKER_STEREO; + else if (num_speakers == 1) + out->u.ulVal = KSAUDIO_SPEAKER_MONO; + + return S_OK; } TRACE("Unimplemented property %s,%u\n", wine_dbgstr_guid(&prop->fmtid), prop->pid);