Mark Harmstone : winealsa: Return PKEY_AudioEndpoint_PhysicalSpeakers device prop.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Dec 29 15:42:43 CST 2014
Module: wine
Branch: master
Commit: acccdce4c45d9e8db8f21deb2e4d764ad21edb9c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=acccdce4c45d9e8db8f21deb2e4d764ad21edb9c
Author: Mark Harmstone <hellas at burntcomma.com>
Date: Sat Dec 27 21:34:48 2014 +0000
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 56f770a..c140437 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 8f93e79..d2fb2d3 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);
More information about the wine-cvs
mailing list