Maarten Lankhorst : mmdevapi: Use openal to enumerate devices.
Alexandre Julliard
julliard at winehq.org
Mon Apr 5 11:23:00 CDT 2010
Module: wine
Branch: master
Commit: 7b36f6658b3d221fb58cedcbc494a5da135f8207
URL: http://source.winehq.org/git/wine.git/?a=commit;h=7b36f6658b3d221fb58cedcbc494a5da135f8207
Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Sun Feb 21 14:48:57 2010 +0100
mmdevapi: Use openal to enumerate devices.
---
dlls/mmdevapi/devenum.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 118 insertions(+), 2 deletions(-)
diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index 62855fa..362855e 100644
--- a/dlls/mmdevapi/devenum.c
+++ b/dlls/mmdevapi/devenum.c
@@ -106,7 +106,7 @@ static HRESULT MMDevPropStore_Create(MMDevice *This, DWORD access, IPropertyStor
* If GUID is null, a random guid will be assigned
* and the device will be created
*/
-static void MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD state, BOOL setdefault)
+static void MMDevice_Create(MMDevice **dev, WCHAR *name, GUID *id, EDataFlow flow, DWORD state, BOOL setdefault)
{
HKEY key, root;
MMDevice *cur;
@@ -190,6 +190,8 @@ done:
else
MMDevice_def_rec = cur;
}
+ if (dev)
+ *dev = cur;
}
static void MMDevice_Destroy(MMDevice *This)
@@ -679,6 +681,113 @@ HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY ke
return hr;
}
+#ifdef HAVE_OPENAL
+
+static void openal_setformat(MMDevice *This, DWORD freq)
+{
+ HRESULT hr;
+ PROPVARIANT pv = { VT_EMPTY };
+
+ hr = MMDevice_GetPropValue(&This->devguid, This->flow, &PKEY_AudioEngine_DeviceFormat, &pv);
+ if (SUCCEEDED(hr) && pv.vt == VT_BLOB)
+ {
+ WAVEFORMATEX *pwfx;
+ pwfx = (WAVEFORMATEX*)pv.u.blob.pBlobData;
+ if (pwfx->nSamplesPerSec != freq)
+ {
+ pwfx->nSamplesPerSec = freq;
+ pwfx->nAvgBytesPerSec = freq * pwfx->nBlockAlign;
+ MMDevice_SetPropValue(&This->devguid, This->flow, &PKEY_AudioEngine_DeviceFormat, &pv);
+ }
+ CoTaskMemFree(pwfx);
+ }
+ else
+ {
+ WAVEFORMATEXTENSIBLE wfxe;
+
+ wfxe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+ wfxe.Format.nChannels = 2;
+ wfxe.Format.wBitsPerSample = 32;
+ wfxe.Format.nBlockAlign = wfxe.Format.nChannels * wfxe.Format.wBitsPerSample/8;
+ wfxe.Format.nSamplesPerSec = freq;
+ wfxe.Format.nAvgBytesPerSec = wfxe.Format.nSamplesPerSec * wfxe.Format.nBlockAlign;
+ wfxe.Format.cbSize = sizeof(wfxe)-sizeof(WAVEFORMATEX);
+ wfxe.Samples.wValidBitsPerSample = 32;
+ wfxe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+ wfxe.dwChannelMask = SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT;
+
+ pv.vt = VT_BLOB;
+ pv.u.blob.cbSize = sizeof(wfxe);
+ pv.u.blob.pBlobData = (BYTE*)&wfxe;
+ MMDevice_SetPropValue(&This->devguid, This->flow, &PKEY_AudioEngine_DeviceFormat, &pv);
+ MMDevice_SetPropValue(&This->devguid, This->flow, &PKEY_AudioEngine_OEMFormat, &pv);
+ }
+}
+
+static void openal_scanrender(void)
+{
+ WCHAR name[MAX_PATH];
+ ALCdevice *dev;
+ const ALCchar *devstr, *defaultstr;
+ EnterCriticalSection(&openal_crst);
+ if (palcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) {
+ defaultstr = palcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
+ devstr = palcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
+ } else {
+ defaultstr = palcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
+ devstr = palcGetString(NULL, ALC_DEVICE_SPECIFIER);
+ }
+ if (devstr && *devstr)
+ do {
+ MMDevice *mmdev;
+ MultiByteToWideChar( CP_UNIXCP, 0, devstr, -1,
+ name, sizeof(name)/sizeof(*name)-1 );
+ name[sizeof(name)/sizeof(*name)-1] = 0;
+ TRACE("Adding %s\n", devstr);
+ dev = palcOpenDevice(devstr);
+ MMDevice_Create(&mmdev, name, NULL, eRender, dev ? DEVICE_STATE_ACTIVE : DEVICE_STATE_NOTPRESENT, !strcmp(devstr, defaultstr));
+ if (dev)
+ {
+ ALint freq = 44100;
+ palcGetIntegerv(dev, ALC_FREQUENCY, 1, &freq);
+ openal_setformat(mmdev, freq);
+ palcCloseDevice(dev);
+ }
+ else
+ WARN("Could not open device: %04x\n", palcGetError(NULL));
+ devstr += strlen(devstr)+1;
+ } while (*devstr);
+ LeaveCriticalSection(&openal_crst);
+}
+
+static void openal_scancapture(void)
+{
+ WCHAR name[MAX_PATH];
+ ALCdevice *dev;
+ const ALCchar *devstr, *defaultstr;
+
+ EnterCriticalSection(&openal_crst);
+ devstr = palcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
+ defaultstr = palcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
+ if (devstr && *devstr)
+ do {
+ ALint freq = 44100;
+ MultiByteToWideChar( CP_UNIXCP, 0, devstr, -1,
+ name, sizeof(name)/sizeof(*name)-1 );
+ name[sizeof(name)/sizeof(*name)-1] = 0;
+ TRACE("Adding %s\n", devstr);
+ dev = palcCaptureOpenDevice(devstr, freq, AL_FORMAT_MONO16, 65536);
+ MMDevice_Create(NULL, name, NULL, eCapture, dev ? DEVICE_STATE_ACTIVE : DEVICE_STATE_NOTPRESENT, !strcmp(devstr, defaultstr));
+ if (dev)
+ palcCaptureCloseDevice(dev);
+ else
+ WARN("Could not open device: %04x\n", palcGetError(NULL));
+ devstr += strlen(devstr)+1;
+ } while (*devstr);
+ LeaveCriticalSection(&openal_crst);
+}
+#endif /*HAVE_OPENAL*/
+
HRESULT MMDevEnum_Create(REFIID riid, void **ppv)
{
MMDevEnumImpl *This = MMDevEnumerator;
@@ -738,11 +847,18 @@ HRESULT MMDevEnum_Create(REFIID riid, void **ppv)
&& SUCCEEDED(MMDevice_GetPropValue(&guid, curflow, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pv))
&& pv.vt == VT_LPWSTR)
{
- MMDevice_Create(pv.u.pwszVal, &guid, curflow,
+ MMDevice_Create(NULL, pv.u.pwszVal, &guid, curflow,
DEVICE_STATE_NOTPRESENT, FALSE);
CoTaskMemFree(pv.u.pwszVal);
}
} while (1);
+#ifdef HAVE_OPENAL
+ if (openal_loaded)
+ {
+ openal_scanrender();
+ openal_scancapture();
+ }
+#endif /*HAVE_OPENAL*/
}
return IUnknown_QueryInterface((IUnknown*)This, riid, ppv);
}
More information about the wine-cvs
mailing list