mmdevapi: Reimplement using a driver system.

This commit is contained in:
Andrew Eikum 2011-04-22 15:25:14 -05:00 committed by Alexandre Julliard
parent 30b8d046ba
commit 5014099928
7 changed files with 218 additions and 2859 deletions

View file

@ -1,9 +1,7 @@
MODULE = mmdevapi.dll
IMPORTS = uuid ole32 oleaut32 user32 advapi32
EXTRALIBS = @FRAMEWORK_OPENAL@
C_SRCS = \
audio.c \
audiovolume.c \
devenum.c \
main.c

View file

@ -1,144 +0,0 @@
/**
* OpenAL cross platform audio library
* Copyright (C) 2008 by authors.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#ifndef AL_ALEXT_H
#define AL_ALEXT_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef AL_LOKI_IMA_ADPCM_format
#define AL_LOKI_IMA_ADPCM_format 1
#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000
#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001
#endif
#ifndef AL_LOKI_WAVE_format
#define AL_LOKI_WAVE_format 1
#define AL_FORMAT_WAVE_EXT 0x10002
#endif
#ifndef AL_EXT_vorbis
#define AL_EXT_vorbis 1
#define AL_FORMAT_VORBIS_EXT 0x10003
#endif
#ifndef AL_LOKI_quadriphonic
#define AL_LOKI_quadriphonic 1
#define AL_FORMAT_QUAD8_LOKI 0x10004
#define AL_FORMAT_QUAD16_LOKI 0x10005
#endif
#ifndef AL_EXT_float32
#define AL_EXT_float32 1
#define AL_FORMAT_MONO_FLOAT32 0x10010
#define AL_FORMAT_STEREO_FLOAT32 0x10011
#endif
#ifndef AL_EXT_double
#define AL_EXT_double 1
#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012
#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013
#endif
#ifndef ALC_LOKI_audio_channel
#define ALC_LOKI_audio_channel 1
#define ALC_CHAN_MAIN_LOKI 0x500001
#define ALC_CHAN_PCM_LOKI 0x500002
#define ALC_CHAN_CD_LOKI 0x500003
#endif
#ifndef ALC_ENUMERATE_ALL_EXT
#define ALC_ENUMERATE_ALL_EXT 1
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
#endif
#ifndef AL_EXT_MCFORMATS
#define AL_EXT_MCFORMATS 1
#define AL_FORMAT_QUAD8 0x1204
#define AL_FORMAT_QUAD16 0x1205
#define AL_FORMAT_QUAD32 0x1206
#define AL_FORMAT_REAR8 0x1207
#define AL_FORMAT_REAR16 0x1208
#define AL_FORMAT_REAR32 0x1209
#define AL_FORMAT_51CHN8 0x120A
#define AL_FORMAT_51CHN16 0x120B
#define AL_FORMAT_51CHN32 0x120C
#define AL_FORMAT_61CHN8 0x120D
#define AL_FORMAT_61CHN16 0x120E
#define AL_FORMAT_61CHN32 0x120F
#define AL_FORMAT_71CHN8 0x1210
#define AL_FORMAT_71CHN16 0x1211
#define AL_FORMAT_71CHN32 0x1212
#endif
#ifndef AL_EXT_MULAW_MCFORMATS
#define AL_EXT_MULAW_MCFORMATS 1
#define AL_FORMAT_MONO_MULAW 0x10014
#define AL_FORMAT_STEREO_MULAW 0x10015
#define AL_FORMAT_QUAD_MULAW 0x10021
#define AL_FORMAT_REAR_MULAW 0x10022
#define AL_FORMAT_51CHN_MULAW 0x10023
#define AL_FORMAT_61CHN_MULAW 0x10024
#define AL_FORMAT_71CHN_MULAW 0x10025
#endif
#ifndef AL_EXT_IMA4
#define AL_EXT_IMA4 1
#define AL_FORMAT_MONO_IMA4 0x1300
#define AL_FORMAT_STEREO_IMA4 0x1301
#endif
#ifndef AL_EXT_STATIC_BUFFER
#define AL_EXT_STATIC_BUFFER 1
typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);
#endif
#endif
#ifndef ALC_EXT_disconnect
#define ALC_EXT_disconnect 1
#define ALC_CONNECTED 0x313
#endif
#ifndef ALC_EXT_thread_local_context
#define ALC_EXT_thread_local_context 1
typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context);
typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context);
ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void);
#endif
#endif
#ifndef AL_EXT_source_distance_model
#define AL_EXT_source_distance_model 1
#define AL_SOURCE_DISTANCE_MODEL 0x200
#endif
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -22,13 +22,6 @@
#include "config.h"
#include <stdarg.h>
#ifdef HAVE_AL_AL_H
#include <AL/al.h>
#include <AL/alc.h>
#elif defined(HAVE_OPENAL_AL_H)
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#endif
#include "windef.h"
#include "winbase.h"
@ -49,8 +42,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
#ifdef HAVE_OPENAL
static const IAudioEndpointVolumeExVtbl AEVImpl_Vtbl;
typedef struct AEVImpl {
@ -297,5 +288,3 @@ static const IAudioEndpointVolumeExVtbl AEVImpl_Vtbl = {
AEV_GetVolumeRange,
AEV_GetVolumeRangeChannel
};
#endif

View file

@ -20,14 +20,6 @@
#include <stdarg.h>
#ifdef HAVE_AL_AL_H
#include <AL/al.h>
#include <AL/alc.h>
#elif defined(HAVE_OPENAL_AL_H)
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#endif
#define NONAMELESSUNION
#define COBJMACROS
#include "windef.h"
@ -267,7 +259,7 @@ static HRESULT MMDevice_SetPropValue(const GUID *devguid, DWORD flow, REFPROPERT
* If GUID is null, a random guid will be assigned
* and the device will be created
*/
static void MMDevice_Create(MMDevice **dev, WCHAR *name, GUID *id, EDataFlow flow, DWORD state, BOOL setdefault)
static MMDevice *MMDevice_Create(WCHAR *name, void *devkey, GUID *id, EDataFlow flow, DWORD state, BOOL setdefault)
{
HKEY key, root;
MMDevice *cur;
@ -277,11 +269,12 @@ static void MMDevice_Create(MMDevice **dev, WCHAR *name, GUID *id, EDataFlow flo
for (i = 0; i < MMDevice_count; ++i)
{
cur = MMDevice_head[i];
if (cur->flow == flow && !lstrcmpW(cur->alname, name))
if (cur->flow == flow && !lstrcmpW(cur->drv_id, name))
{
LONG ret;
/* Same device, update state */
cur->state = state;
cur->key = devkey;
StringFromGUID2(&cur->devguid, guidstr, sizeof(guidstr)/sizeof(*guidstr));
ret = RegOpenKeyExW(flow == eRender ? key_render : key_capture, guidstr, 0, KEY_WRITE, &key);
if (ret == ERROR_SUCCESS)
@ -295,15 +288,19 @@ static void MMDevice_Create(MMDevice **dev, WCHAR *name, GUID *id, EDataFlow flo
/* No device found, allocate new one */
cur = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur));
if (!cur)
return;
cur->alname = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name)+1)*sizeof(WCHAR));
if (!cur->alname)
if (!cur){
HeapFree(GetProcessHeap(), 0, devkey);
return NULL;
}
cur->drv_id = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name)+1)*sizeof(WCHAR));
if (!cur->drv_id)
{
HeapFree(GetProcessHeap(), 0, cur);
return;
HeapFree(GetProcessHeap(), 0, devkey);
return NULL;
}
lstrcpyW(cur->alname, name);
lstrcpyW(cur->drv_id, name);
cur->key = devkey;
cur->IMMDevice_iface.lpVtbl = &MMDeviceVtbl;
cur->IMMEndpoint_iface.lpVtbl = &MMEndpointVtbl;
cur->ref = 0;
@ -311,7 +308,6 @@ static void MMDevice_Create(MMDevice **dev, WCHAR *name, GUID *id, EDataFlow flo
cur->crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MMDevice.crst");
cur->flow = flow;
cur->state = state;
cur->device = NULL;
if (!id)
{
id = &cur->devguid;
@ -352,14 +348,125 @@ done:
else
MMDevice_def_rec = cur;
}
if (dev)
*dev = cur;
return cur;
}
static HRESULT load_devices_from_reg(void)
{
DWORD i = 0;
HKEY root, cur;
LONG ret;
DWORD curflow;
ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, software_mmdevapi, 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &root, NULL);
if (ret == ERROR_SUCCESS)
ret = RegCreateKeyExW(root, reg_capture, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &key_capture, NULL);
if (ret == ERROR_SUCCESS)
ret = RegCreateKeyExW(root, reg_render, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &key_render, NULL);
RegCloseKey(root);
cur = key_capture;
curflow = eCapture;
if (ret != ERROR_SUCCESS)
{
RegCloseKey(key_capture);
key_render = key_capture = NULL;
WARN("Couldn't create key: %u\n", ret);
return E_FAIL;
}
do {
WCHAR guidvalue[39];
GUID guid;
DWORD len;
PROPVARIANT pv = { VT_EMPTY };
len = sizeof(guidvalue)/sizeof(guidvalue[0]);
ret = RegEnumKeyExW(cur, i++, guidvalue, &len, NULL, NULL, NULL, NULL);
if (ret == ERROR_NO_MORE_ITEMS)
{
if (cur == key_capture)
{
cur = key_render;
curflow = eRender;
i = 0;
continue;
}
break;
}
if (ret != ERROR_SUCCESS)
continue;
if (SUCCEEDED(CLSIDFromString(guidvalue, &guid))
&& SUCCEEDED(MMDevice_GetPropValue(&guid, curflow, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pv))
&& pv.vt == VT_LPWSTR)
{
MMDevice_Create(pv.u.pwszVal, NULL, &guid, curflow,
DEVICE_STATE_NOTPRESENT, FALSE);
CoTaskMemFree(pv.u.pwszVal);
}
} while (1);
return S_OK;
}
static HRESULT set_format(MMDevice *dev)
{
HRESULT hr;
IAudioClient *client;
WAVEFORMATEX *fmt;
PROPVARIANT pv = { VT_EMPTY };
hr = drvs.pGetAudioEndpoint(dev->key, &dev->IMMDevice_iface, dev->flow, &client);
if(FAILED(hr))
return hr;
hr = IAudioClient_GetMixFormat(client, &fmt);
if(FAILED(hr)){
IAudioClient_Release(client);
return hr;
}
IAudioClient_Release(client);
pv.vt = VT_BLOB;
pv.u.blob.cbSize = sizeof(WAVEFORMATEX) + fmt->cbSize;
pv.u.blob.pBlobData = (BYTE*)fmt;
MMDevice_SetPropValue(&dev->devguid, dev->flow,
&PKEY_AudioEngine_DeviceFormat, &pv);
MMDevice_SetPropValue(&dev->devguid, dev->flow,
&PKEY_AudioEngine_OEMFormat, &pv);
return S_OK;
}
static HRESULT load_driver_devices(EDataFlow flow)
{
WCHAR **ids;
void **keys;
UINT num, def, i;
HRESULT hr;
hr = drvs.pGetEndpointIDs(flow, &ids, &keys, &num, &def);
if(FAILED(hr))
return hr;
for(i = 0; i < num; ++i){
MMDevice *dev;
dev = MMDevice_Create(ids[i], keys[i], NULL, flow, DEVICE_STATE_ACTIVE,
def == i);
set_format(dev);
HeapFree(GetProcessHeap(), 0, ids[i]);
}
HeapFree(GetProcessHeap(), 0, keys);
HeapFree(GetProcessHeap(), 0, ids);
return S_OK;
}
static void MMDevice_Destroy(MMDevice *This)
{
DWORD i;
TRACE("Freeing %s\n", debugstr_w(This->alname));
TRACE("Freeing %s\n", debugstr_w(This->drv_id));
/* Since this function is called at destruction time, reordering of the list is unimportant */
for (i = 0; i < MMDevice_count; ++i)
{
@ -369,13 +476,10 @@ static void MMDevice_Destroy(MMDevice *This)
break;
}
}
#ifdef HAVE_OPENAL
if (This->device)
palcCloseDevice(This->device);
#endif
This->crst.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->crst);
HeapFree(GetProcessHeap(), 0, This->alname);
HeapFree(GetProcessHeap(), 0, This->drv_id);
HeapFree(GetProcessHeap(), 0, This->key);
HeapFree(GetProcessHeap(), 0, This);
}
@ -429,8 +533,6 @@ static ULONG WINAPI MMDevice_Release(IMMDevice *iface)
static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD clsctx, PROPVARIANT *params, void **ppv)
{
HRESULT hr = E_NOINTERFACE;
#ifdef HAVE_OPENAL
MMDevice *This = impl_from_IMMDevice(iface);
TRACE("(%p)->(%p,%x,%p,%p)\n", iface, riid, clsctx, params, ppv);
@ -438,14 +540,9 @@ static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD cls
if (!ppv)
return E_POINTER;
if (!openal_loaded)
{
WARN("OpenAL is still not loaded\n");
hr = AUDCLNT_E_SERVICE_NOT_RUNNING;
}
else if (IsEqualIID(riid, &IID_IAudioClient))
hr = AudioClient_Create(This, (IAudioClient**)ppv);
else if (IsEqualIID(riid, &IID_IAudioEndpointVolume))
if (IsEqualIID(riid, &IID_IAudioClient)){
hr = drvs.pGetAudioEndpoint(This->key, iface, This->flow, (IAudioClient**)ppv);
}else if (IsEqualIID(riid, &IID_IAudioEndpointVolume))
hr = AudioEndpointVolume_Create(This, (IAudioEndpointVolume**)ppv);
else if (IsEqualIID(riid, &IID_IAudioSessionManager)
|| IsEqualIID(riid, &IID_IAudioSessionManager2))
@ -509,10 +606,6 @@ static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD cls
}
else
ERR("Invalid/unknown iid %s\n", debugstr_guid(riid));
#else
if (!ppv) return E_POINTER;
hr = AUDCLNT_E_SERVICE_NOT_RUNNING;
#endif
if (FAILED(hr))
*ppv = NULL;
@ -727,205 +820,12 @@ static const IMMDeviceCollectionVtbl MMDevColVtbl =
MMDevCol_Item
};
#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 int blacklist_pulse;
static int blacklist(const char *dev) {
#ifdef __linux__
if (!strncmp(dev, "OSS ", 4))
return 1;
#endif
if (blacklist_pulse && !strncmp(dev, "PulseAudio ", 11))
return 1;
if (!strncmp(dev, "ALSA ", 5) && strstr(dev, "hw:"))
return 1;
if (!strncmp(dev, "PortAudio ", 10))
return 1;
return 0;
}
static void pulse_fixup(const char *devstr, const char **defstr, int render) {
static int warned;
int default_pulse;
if (render && !blacklist_pulse && !local_contexts)
blacklist_pulse = 1;
if (!blacklist_pulse || !devstr || !*devstr)
return;
default_pulse = !strncmp(*defstr, "PulseAudio ", 11);
while (*devstr && !strncmp(devstr, "PulseAudio ", 11))
devstr += strlen(devstr) + 1;
/* Could still be a newer version, so check for 1.11 if more devices are enabled */
if (render && *devstr) {
ALCdevice *dev = palcOpenDevice(devstr);
ALCcontext *ctx = palcCreateContext(dev, NULL);
if (ctx) {
const char *ver;
setALContext(ctx);
ver = palGetString(AL_VERSION);
popALContext();
palcDestroyContext(ctx);
if (!strcmp(ver, "1.1 ALSOFT 1.11.753")) {
blacklist_pulse = 0;
palcCloseDevice(dev);
return;
}
}
if (dev)
palcCloseDevice(dev);
}
if (!warned++) {
ERR("Disabling pulseaudio because of old openal version\n");
ERR("Please upgrade to openal-soft v1.12 or newer\n");
}
TRACE("New default: %s\n", devstr);
if (default_pulse)
*defstr = devstr;
}
static void openal_scanrender(void)
{
WCHAR name[MAX_PATH];
ALCdevice *dev;
const ALCchar *devstr, *defaultstr;
int defblacklisted;
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);
}
pulse_fixup(devstr, &defaultstr, 1);
defblacklisted = blacklist(defaultstr);
if (defblacklisted)
WARN("Disabling blacklist because %s is blacklisted\n", defaultstr);
if (devstr)
for (; *devstr; devstr += strlen(devstr)+1) {
MMDevice *mmdev;
MultiByteToWideChar( CP_UNIXCP, 0, devstr, -1,
name, sizeof(name)/sizeof(*name)-1 );
name[sizeof(name)/sizeof(*name)-1] = 0;
/* Only enable blacklist if the default device isn't blacklisted */
if (!defblacklisted && blacklist(devstr)) {
WARN("Not adding %s: device is blacklisted\n", devstr);
continue;
}
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));
}
LeaveCriticalSection(&openal_crst);
}
static void openal_scancapture(void)
{
WCHAR name[MAX_PATH];
ALCdevice *dev;
const ALCchar *devstr, *defaultstr;
int defblacklisted;
EnterCriticalSection(&openal_crst);
devstr = palcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
defaultstr = palcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
pulse_fixup(devstr, &defaultstr, 0);
defblacklisted = blacklist(defaultstr);
if (defblacklisted)
WARN("Disabling blacklist because %s is blacklisted\n", defaultstr);
if (devstr && *devstr)
for (; *devstr; devstr += strlen(devstr)+1) {
MMDevice *mmdev;
ALint freq = 44100;
MultiByteToWideChar( CP_UNIXCP, 0, devstr, -1,
name, sizeof(name)/sizeof(*name)-1 );
name[sizeof(name)/sizeof(*name)-1] = 0;
if (!defblacklisted && blacklist(devstr)) {
WARN("Not adding %s: device is blacklisted\n", devstr);
continue;
}
TRACE("Adding %s\n", devstr);
dev = palcCaptureOpenDevice(devstr, freq, AL_FORMAT_MONO16, 65536);
MMDevice_Create(&mmdev, name, NULL, eCapture, dev ? DEVICE_STATE_ACTIVE : DEVICE_STATE_NOTPRESENT, !strcmp(devstr, defaultstr));
if (dev) {
openal_setformat(mmdev, freq);
palcCaptureCloseDevice(dev);
} else
WARN("Could not open device: %04x\n", palcGetError(NULL));
}
LeaveCriticalSection(&openal_crst);
}
#endif /*HAVE_OPENAL*/
HRESULT MMDevEnum_Create(REFIID riid, void **ppv)
{
MMDevEnumImpl *This = MMDevEnumerator;
if (!This)
{
DWORD i = 0;
HKEY root, cur;
LONG ret;
DWORD curflow;
This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
*ppv = NULL;
if (!This)
@ -934,62 +834,9 @@ HRESULT MMDevEnum_Create(REFIID riid, void **ppv)
This->IMMDeviceEnumerator_iface.lpVtbl = &MMDevEnumVtbl;
MMDevEnumerator = This;
ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, software_mmdevapi, 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &root, NULL);
if (ret == ERROR_SUCCESS)
ret = RegCreateKeyExW(root, reg_capture, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &key_capture, NULL);
if (ret == ERROR_SUCCESS)
ret = RegCreateKeyExW(root, reg_render, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &key_render, NULL);
RegCloseKey(root);
cur = key_capture;
curflow = eCapture;
if (ret != ERROR_SUCCESS)
{
RegCloseKey(key_capture);
key_render = key_capture = NULL;
WARN("Couldn't create key: %u\n", ret);
return E_FAIL;
}
else do {
WCHAR guidvalue[39];
GUID guid;
DWORD len;
PROPVARIANT pv = { VT_EMPTY };
len = sizeof(guidvalue)/sizeof(guidvalue[0]);
ret = RegEnumKeyExW(cur, i++, guidvalue, &len, NULL, NULL, NULL, NULL);
if (ret == ERROR_NO_MORE_ITEMS)
{
if (cur == key_capture)
{
cur = key_render;
curflow = eRender;
i = 0;
continue;
}
break;
}
if (ret != ERROR_SUCCESS)
continue;
if (SUCCEEDED(CLSIDFromString(guidvalue, &guid))
&& SUCCEEDED(MMDevice_GetPropValue(&guid, curflow, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pv))
&& pv.vt == VT_LPWSTR)
{
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();
}
else
FIXME("OpenAL support not enabled, application will not find sound devices\n");
#else
ERR("OpenAL support not compiled in, application will not find sound devices\n");
#endif /*HAVE_OPENAL*/
load_devices_from_reg();
load_driver_devices(eRender);
load_driver_devices(eCapture);
}
return IUnknown_QueryInterface((IUnknown*)This, riid, ppv);
}

View file

@ -1,5 +1,6 @@
/*
* Copyright 2009 Maarten Lankhorst
* Copyright 2011 Andrew Eikum for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -21,14 +22,6 @@
#include <stdarg.h>
#ifdef HAVE_AL_AL_H
#include <AL/al.h>
#include <AL/alc.h>
#elif defined(HAVE_OPENAL_AL_H)
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#endif
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
@ -48,274 +41,84 @@
#include "endpointvolume.h"
#include "audiopolicy.h"
#include "devpkey.h"
#include "winreg.h"
#include "mmdevapi.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
#ifdef HAVE_OPENAL
static HINSTANCE instance;
int local_contexts;
DriverFuncs drvs;
static CRITICAL_SECTION_DEBUG openal_crst_debug =
static BOOL load_driver(const WCHAR *name)
{
0, 0, &openal_crst,
{ &openal_crst_debug.ProcessLocksList,
&openal_crst_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": openal_crst_debug") }
};
CRITICAL_SECTION openal_crst = { &openal_crst_debug, -1, 0, 0, 0, 0 };
WCHAR driver_module[264];
static const WCHAR wineW[] = {'w','i','n','e',0};
static const WCHAR dotdrvW[] = {'.','d','r','v',0};
static void *openal_handle = RTLD_DEFAULT;
int openal_loaded;
#ifdef SONAME_LIBOPENAL
LPALCCREATECONTEXT palcCreateContext = NULL;
LPALCMAKECONTEXTCURRENT palcMakeContextCurrent = NULL;
LPALCPROCESSCONTEXT palcProcessContext = NULL;
LPALCSUSPENDCONTEXT palcSuspendContext = NULL;
LPALCDESTROYCONTEXT palcDestroyContext = NULL;
LPALCGETCURRENTCONTEXT palcGetCurrentContext = NULL;
LPALCGETCONTEXTSDEVICE palcGetContextsDevice = NULL;
LPALCOPENDEVICE palcOpenDevice = NULL;
LPALCCLOSEDEVICE palcCloseDevice = NULL;
LPALCGETERROR palcGetError = NULL;
LPALCISEXTENSIONPRESENT palcIsExtensionPresent = NULL;
LPALCGETPROCADDRESS palcGetProcAddress = NULL;
LPALCGETENUMVALUE palcGetEnumValue = NULL;
LPALCGETSTRING palcGetString = NULL;
LPALCGETINTEGERV palcGetIntegerv = NULL;
LPALCCAPTUREOPENDEVICE palcCaptureOpenDevice = NULL;
LPALCCAPTURECLOSEDEVICE palcCaptureCloseDevice = NULL;
LPALCCAPTURESTART palcCaptureStart = NULL;
LPALCCAPTURESTOP palcCaptureStop = NULL;
LPALCCAPTURESAMPLES palcCaptureSamples = NULL;
LPALENABLE palEnable = NULL;
LPALDISABLE palDisable = NULL;
LPALISENABLED palIsEnabled = NULL;
LPALGETSTRING palGetString = NULL;
LPALGETBOOLEANV palGetBooleanv = NULL;
LPALGETINTEGERV palGetIntegerv = NULL;
LPALGETFLOATV palGetFloatv = NULL;
LPALGETDOUBLEV palGetDoublev = NULL;
LPALGETBOOLEAN palGetBoolean = NULL;
LPALGETINTEGER palGetInteger = NULL;
LPALGETFLOAT palGetFloat = NULL;
LPALGETDOUBLE palGetDouble = NULL;
LPALGETERROR palGetError = NULL;
LPALISEXTENSIONPRESENT palIsExtensionPresent = NULL;
LPALGETPROCADDRESS palGetProcAddress = NULL;
LPALGETENUMVALUE palGetEnumValue = NULL;
LPALLISTENERF palListenerf = NULL;
LPALLISTENER3F palListener3f = NULL;
LPALLISTENERFV palListenerfv = NULL;
LPALLISTENERI palListeneri = NULL;
LPALLISTENER3I palListener3i = NULL;
LPALLISTENERIV palListeneriv = NULL;
LPALGETLISTENERF palGetListenerf = NULL;
LPALGETLISTENER3F palGetListener3f = NULL;
LPALGETLISTENERFV palGetListenerfv = NULL;
LPALGETLISTENERI palGetListeneri = NULL;
LPALGETLISTENER3I palGetListener3i = NULL;
LPALGETLISTENERIV palGetListeneriv = NULL;
LPALGENSOURCES palGenSources = NULL;
LPALDELETESOURCES palDeleteSources = NULL;
LPALISSOURCE palIsSource = NULL;
LPALSOURCEF palSourcef = NULL;
LPALSOURCE3F palSource3f = NULL;
LPALSOURCEFV palSourcefv = NULL;
LPALSOURCEI palSourcei = NULL;
LPALSOURCE3I palSource3i = NULL;
LPALSOURCEIV palSourceiv = NULL;
LPALGETSOURCEF palGetSourcef = NULL;
LPALGETSOURCE3F palGetSource3f = NULL;
LPALGETSOURCEFV palGetSourcefv = NULL;
LPALGETSOURCEI palGetSourcei = NULL;
LPALGETSOURCE3I palGetSource3i = NULL;
LPALGETSOURCEIV palGetSourceiv = NULL;
LPALSOURCEPLAYV palSourcePlayv = NULL;
LPALSOURCESTOPV palSourceStopv = NULL;
LPALSOURCEREWINDV palSourceRewindv = NULL;
LPALSOURCEPAUSEV palSourcePausev = NULL;
LPALSOURCEPLAY palSourcePlay = NULL;
LPALSOURCESTOP palSourceStop = NULL;
LPALSOURCEREWIND palSourceRewind = NULL;
LPALSOURCEPAUSE palSourcePause = NULL;
LPALSOURCEQUEUEBUFFERS palSourceQueueBuffers = NULL;
LPALSOURCEUNQUEUEBUFFERS palSourceUnqueueBuffers = NULL;
LPALGENBUFFERS palGenBuffers = NULL;
LPALDELETEBUFFERS palDeleteBuffers = NULL;
LPALISBUFFER palIsBuffer = NULL;
LPALBUFFERF palBufferf = NULL;
LPALBUFFER3F palBuffer3f = NULL;
LPALBUFFERFV palBufferfv = NULL;
LPALBUFFERI palBufferi = NULL;
LPALBUFFER3I palBuffer3i = NULL;
LPALBUFFERIV palBufferiv = NULL;
LPALGETBUFFERF palGetBufferf = NULL;
LPALGETBUFFER3F palGetBuffer3f = NULL;
LPALGETBUFFERFV palGetBufferfv = NULL;
LPALGETBUFFERI palGetBufferi = NULL;
LPALGETBUFFER3I palGetBuffer3i = NULL;
LPALGETBUFFERIV palGetBufferiv = NULL;
LPALBUFFERDATA palBufferData = NULL;
LPALDOPPLERFACTOR palDopplerFactor = NULL;
LPALDOPPLERVELOCITY palDopplerVelocity = NULL;
LPALDISTANCEMODEL palDistanceModel = NULL;
LPALSPEEDOFSOUND palSpeedOfSound = NULL;
#endif
lstrcpyW(driver_module, wineW);
lstrcatW(driver_module, name);
lstrcatW(driver_module, dotdrvW);
typeof(alcGetCurrentContext) *get_context;
typeof(alcMakeContextCurrent) *set_context;
TRACE("Attempting to load %s\n", wine_dbgstr_w(driver_module));
static void load_libopenal(void)
{
DWORD failed = 0;
#ifdef SONAME_LIBOPENAL
char error[128];
openal_handle = wine_dlopen(SONAME_LIBOPENAL, RTLD_NOW, error, sizeof(error));
if (!openal_handle)
{
ERR("Couldn't load " SONAME_LIBOPENAL ": %s\n", error);
return;
drvs.module = LoadLibraryW(driver_module);
if(!drvs.module){
TRACE("Unable to load %s: %u\n", wine_dbgstr_w(driver_module),
GetLastError());
return FALSE;
}
#define LOAD_FUNCPTR(f) \
if((p##f = wine_dlsym(openal_handle, #f, NULL, 0)) == NULL) { \
ERR("Couldn't lookup %s in libopenal\n", #f); \
failed = 1; \
}
#define LDFC(n) do { drvs.p##n = (void*)GetProcAddress(drvs.module, #n);\
if(!drvs.p##n) return FALSE; } while(0);
LDFC(GetEndpointIDs);
LDFC(GetAudioEndpoint);
#undef LDFC
LOAD_FUNCPTR(alcCreateContext);
LOAD_FUNCPTR(alcMakeContextCurrent);
LOAD_FUNCPTR(alcProcessContext);
LOAD_FUNCPTR(alcSuspendContext);
LOAD_FUNCPTR(alcDestroyContext);
LOAD_FUNCPTR(alcGetCurrentContext);
LOAD_FUNCPTR(alcGetContextsDevice);
LOAD_FUNCPTR(alcOpenDevice);
LOAD_FUNCPTR(alcCloseDevice);
LOAD_FUNCPTR(alcGetError);
LOAD_FUNCPTR(alcIsExtensionPresent);
LOAD_FUNCPTR(alcGetProcAddress);
LOAD_FUNCPTR(alcGetEnumValue);
LOAD_FUNCPTR(alcGetString);
LOAD_FUNCPTR(alcGetIntegerv);
LOAD_FUNCPTR(alcCaptureOpenDevice);
LOAD_FUNCPTR(alcCaptureCloseDevice);
LOAD_FUNCPTR(alcCaptureStart);
LOAD_FUNCPTR(alcCaptureStop);
LOAD_FUNCPTR(alcCaptureSamples);
LOAD_FUNCPTR(alEnable);
LOAD_FUNCPTR(alDisable);
LOAD_FUNCPTR(alIsEnabled);
LOAD_FUNCPTR(alGetString);
LOAD_FUNCPTR(alGetBooleanv);
LOAD_FUNCPTR(alGetIntegerv);
LOAD_FUNCPTR(alGetFloatv);
LOAD_FUNCPTR(alGetDoublev);
LOAD_FUNCPTR(alGetBoolean);
LOAD_FUNCPTR(alGetInteger);
LOAD_FUNCPTR(alGetFloat);
LOAD_FUNCPTR(alGetDouble);
LOAD_FUNCPTR(alGetError);
LOAD_FUNCPTR(alIsExtensionPresent);
LOAD_FUNCPTR(alGetProcAddress);
LOAD_FUNCPTR(alGetEnumValue);
LOAD_FUNCPTR(alListenerf);
LOAD_FUNCPTR(alListener3f);
LOAD_FUNCPTR(alListenerfv);
LOAD_FUNCPTR(alListeneri);
LOAD_FUNCPTR(alListener3i);
LOAD_FUNCPTR(alListeneriv);
LOAD_FUNCPTR(alGetListenerf);
LOAD_FUNCPTR(alGetListener3f);
LOAD_FUNCPTR(alGetListenerfv);
LOAD_FUNCPTR(alGetListeneri);
LOAD_FUNCPTR(alGetListener3i);
LOAD_FUNCPTR(alGetListeneriv);
LOAD_FUNCPTR(alGenSources);
LOAD_FUNCPTR(alDeleteSources);
LOAD_FUNCPTR(alIsSource);
LOAD_FUNCPTR(alSourcef);
LOAD_FUNCPTR(alSource3f);
LOAD_FUNCPTR(alSourcefv);
LOAD_FUNCPTR(alSourcei);
LOAD_FUNCPTR(alSource3i);
LOAD_FUNCPTR(alSourceiv);
LOAD_FUNCPTR(alGetSourcef);
LOAD_FUNCPTR(alGetSource3f);
LOAD_FUNCPTR(alGetSourcefv);
LOAD_FUNCPTR(alGetSourcei);
LOAD_FUNCPTR(alGetSource3i);
LOAD_FUNCPTR(alGetSourceiv);
LOAD_FUNCPTR(alSourcePlayv);
LOAD_FUNCPTR(alSourceStopv);
LOAD_FUNCPTR(alSourceRewindv);
LOAD_FUNCPTR(alSourcePausev);
LOAD_FUNCPTR(alSourcePlay);
LOAD_FUNCPTR(alSourceStop);
LOAD_FUNCPTR(alSourceRewind);
LOAD_FUNCPTR(alSourcePause);
LOAD_FUNCPTR(alSourceQueueBuffers);
LOAD_FUNCPTR(alSourceUnqueueBuffers);
LOAD_FUNCPTR(alGenBuffers);
LOAD_FUNCPTR(alDeleteBuffers);
LOAD_FUNCPTR(alIsBuffer);
LOAD_FUNCPTR(alBufferf);
LOAD_FUNCPTR(alBuffer3f);
LOAD_FUNCPTR(alBufferfv);
LOAD_FUNCPTR(alBufferi);
LOAD_FUNCPTR(alBuffer3i);
LOAD_FUNCPTR(alBufferiv);
LOAD_FUNCPTR(alGetBufferf);
LOAD_FUNCPTR(alGetBuffer3f);
LOAD_FUNCPTR(alGetBufferfv);
LOAD_FUNCPTR(alGetBufferi);
LOAD_FUNCPTR(alGetBuffer3i);
LOAD_FUNCPTR(alGetBufferiv);
LOAD_FUNCPTR(alBufferData);
LOAD_FUNCPTR(alDopplerFactor);
LOAD_FUNCPTR(alDopplerVelocity);
LOAD_FUNCPTR(alDistanceModel);
LOAD_FUNCPTR(alSpeedOfSound);
#undef LOAD_FUNCPTR
#endif
TRACE("Successfully loaded %s\n", wine_dbgstr_w(driver_module));
if (failed)
{
WARN("Unloading openal\n");
if (openal_handle != RTLD_DEFAULT)
wine_dlclose(openal_handle, NULL, 0);
openal_handle = NULL;
openal_loaded = 0;
}
else
{
openal_loaded = 1;
local_contexts = palcIsExtensionPresent(NULL, "ALC_EXT_thread_local_context");
if (local_contexts)
{
set_context = palcGetProcAddress(NULL, "alcSetThreadContext");
get_context = palcGetProcAddress(NULL, "alcGetThreadContext");
if (!set_context || !get_context)
{
ERR("TLS advertised but functions not found, disabling thread local context\n");
local_contexts = 0;
}
}
if (!local_contexts)
{
set_context = palcMakeContextCurrent;
get_context = palcGetCurrentContext;
}
}
return TRUE;
}
#endif /*HAVE_OPENAL*/
static BOOL init_driver(void)
{
static const WCHAR alsaW[] = {'a','l','s','a',0};
static const WCHAR ossW[] = {'o','s','s',0};
static const WCHAR coreaudioW[] = {'c','o','r','e','a','u','d','i','o',0};
static const WCHAR *default_drivers[] = { alsaW, coreaudioW, ossW };
static const WCHAR drv_key[] = {'S','o','f','t','w','a','r','e','\\',
'W','i','n','e','\\','D','r','i','v','e','r','s',0};
static const WCHAR drv_value[] = {'A','u','d','i','o',0};
HKEY key;
UINT i;
static HINSTANCE instance;
if(drvs.module)
return TRUE;
if(RegOpenKeyW(HKEY_CURRENT_USER, drv_key, &key) == ERROR_SUCCESS){
WCHAR driver_name[256];
DWORD size = sizeof(driver_name);
if(RegQueryValueExW(key, drv_value, 0, NULL, (BYTE*)driver_name,
&size) == ERROR_SUCCESS){
BOOL ret = load_driver(driver_name);
RegCloseKey(key);
if(!ret)
ERR("Failed to load driver: %s\n", wine_dbgstr_w(driver_name));
return ret;
}
RegCloseKey(key);
}
for(i = 0; i < sizeof(default_drivers)/sizeof(*default_drivers); ++i)
if(load_driver(default_drivers[i]))
return TRUE;
return FALSE;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
@ -326,9 +129,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
case DLL_PROCESS_ATTACH:
instance = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
#ifdef HAVE_OPENAL
load_libopenal();
#endif /*HAVE_OPENAL*/
break;
case DLL_PROCESS_DETACH:
MMDevEnum_Free();
@ -429,6 +229,11 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
int i = 0;
TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
if(!init_driver()){
ERR("Driver initialization failed\n");
return E_FAIL;
}
if (ppv == NULL) {
WARN("invalid parameter\n");
return E_INVALIDARG;

View file

@ -25,6 +25,22 @@ extern void MMDevEnum_Free(void);
extern HRESULT MMDevice_GetPropValue(const GUID *devguid, DWORD flow, REFPROPERTYKEY key, PROPVARIANT *pv);
typedef struct _DriverFuncs {
HMODULE module;
/* ids gets an array of human-friendly endpoint names
* keys gets an array of driver-specific stuff that is used
* in GetAudioEndpoint to identify the endpoint
* it is the caller's responsibility to free both arrays, and
* all of the elements in both arrays with HeapFree() */
HRESULT WINAPI (*pGetEndpointIDs)(EDataFlow flow, WCHAR ***ids,
void ***keys, UINT *num, UINT *default_index);
HRESULT WINAPI (*pGetAudioEndpoint)(void *key, IMMDevice *dev,
EDataFlow dataflow, IAudioClient **out);
} DriverFuncs;
extern DriverFuncs drvs;
typedef struct MMDevice {
IMMDevice IMMDevice_iface;
IMMEndpoint IMMEndpoint_iface;
@ -35,252 +51,9 @@ typedef struct MMDevice {
EDataFlow flow;
DWORD state;
GUID devguid;
WCHAR *alname;
void *device, *ctx;
WCHAR *drv_id;
void *key;
} MMDevice;
extern HRESULT AudioClient_Create(MMDevice *parent, IAudioClient **ppv);
extern HRESULT AudioEndpointVolume_Create(MMDevice *parent, IAudioEndpointVolume **ppv);
#ifdef HAVE_OPENAL
#include "alext.h"
/* All openal functions */
extern int openal_loaded;
#ifdef SONAME_LIBOPENAL
extern LPALCCREATECONTEXT palcCreateContext;
extern LPALCMAKECONTEXTCURRENT palcMakeContextCurrent;
extern LPALCPROCESSCONTEXT palcProcessContext;
extern LPALCSUSPENDCONTEXT palcSuspendContext;
extern LPALCDESTROYCONTEXT palcDestroyContext;
extern LPALCGETCURRENTCONTEXT palcGetCurrentContext;
extern LPALCGETCONTEXTSDEVICE palcGetContextsDevice;
extern LPALCOPENDEVICE palcOpenDevice;
extern LPALCCLOSEDEVICE palcCloseDevice;
extern LPALCGETERROR palcGetError;
extern LPALCISEXTENSIONPRESENT palcIsExtensionPresent;
extern LPALCGETPROCADDRESS palcGetProcAddress;
extern LPALCGETENUMVALUE palcGetEnumValue;
extern LPALCGETSTRING palcGetString;
extern LPALCGETINTEGERV palcGetIntegerv;
extern LPALCCAPTUREOPENDEVICE palcCaptureOpenDevice;
extern LPALCCAPTURECLOSEDEVICE palcCaptureCloseDevice;
extern LPALCCAPTURESTART palcCaptureStart;
extern LPALCCAPTURESTOP palcCaptureStop;
extern LPALCCAPTURESAMPLES palcCaptureSamples;
extern LPALENABLE palEnable;
extern LPALDISABLE palDisable;
extern LPALISENABLED palIsEnabled;
extern LPALGETSTRING palGetString;
extern LPALGETBOOLEANV palGetBooleanv;
extern LPALGETINTEGERV palGetIntegerv;
extern LPALGETFLOATV palGetFloatv;
extern LPALGETDOUBLEV palGetDoublev;
extern LPALGETBOOLEAN palGetBoolean;
extern LPALGETINTEGER palGetInteger;
extern LPALGETFLOAT palGetFloat;
extern LPALGETDOUBLE palGetDouble;
extern LPALGETERROR palGetError;
extern LPALISEXTENSIONPRESENT palIsExtensionPresent;
extern LPALGETPROCADDRESS palGetProcAddress;
extern LPALGETENUMVALUE palGetEnumValue;
extern LPALLISTENERF palListenerf;
extern LPALLISTENER3F palListener3f;
extern LPALLISTENERFV palListenerfv;
extern LPALLISTENERI palListeneri;
extern LPALLISTENER3I palListener3i;
extern LPALLISTENERIV palListeneriv;
extern LPALGETLISTENERF palGetListenerf;
extern LPALGETLISTENER3F palGetListener3f;
extern LPALGETLISTENERFV palGetListenerfv;
extern LPALGETLISTENERI palGetListeneri;
extern LPALGETLISTENER3I palGetListener3i;
extern LPALGETLISTENERIV palGetListeneriv;
extern LPALGENSOURCES palGenSources;
extern LPALDELETESOURCES palDeleteSources;
extern LPALISSOURCE palIsSource;
extern LPALSOURCEF palSourcef;
extern LPALSOURCE3F palSource3f;
extern LPALSOURCEFV palSourcefv;
extern LPALSOURCEI palSourcei;
extern LPALSOURCE3I palSource3i;
extern LPALSOURCEIV palSourceiv;
extern LPALGETSOURCEF palGetSourcef;
extern LPALGETSOURCE3F palGetSource3f;
extern LPALGETSOURCEFV palGetSourcefv;
extern LPALGETSOURCEI palGetSourcei;
extern LPALGETSOURCE3I palGetSource3i;
extern LPALGETSOURCEIV palGetSourceiv;
extern LPALSOURCEPLAYV palSourcePlayv;
extern LPALSOURCESTOPV palSourceStopv;
extern LPALSOURCEREWINDV palSourceRewindv;
extern LPALSOURCEPAUSEV palSourcePausev;
extern LPALSOURCEPLAY palSourcePlay;
extern LPALSOURCESTOP palSourceStop;
extern LPALSOURCEREWIND palSourceRewind;
extern LPALSOURCEPAUSE palSourcePause;
extern LPALSOURCEQUEUEBUFFERS palSourceQueueBuffers;
extern LPALSOURCEUNQUEUEBUFFERS palSourceUnqueueBuffers;
extern LPALGENBUFFERS palGenBuffers;
extern LPALDELETEBUFFERS palDeleteBuffers;
extern LPALISBUFFER palIsBuffer;
extern LPALBUFFERF palBufferf;
extern LPALBUFFER3F palBuffer3f;
extern LPALBUFFERFV palBufferfv;
extern LPALBUFFERI palBufferi;
extern LPALBUFFER3I palBuffer3i;
extern LPALBUFFERIV palBufferiv;
extern LPALGETBUFFERF palGetBufferf;
extern LPALGETBUFFER3F palGetBuffer3f;
extern LPALGETBUFFERFV palGetBufferfv;
extern LPALGETBUFFERI palGetBufferi;
extern LPALGETBUFFER3I palGetBuffer3i;
extern LPALGETBUFFERIV palGetBufferiv;
extern LPALBUFFERDATA palBufferData;
extern LPALDOPPLERFACTOR palDopplerFactor;
extern LPALDOPPLERVELOCITY palDopplerVelocity;
extern LPALDISTANCEMODEL palDistanceModel;
extern LPALSPEEDOFSOUND palSpeedOfSound;
#else
#define palcCreateContext alcCreateContext
#define palcMakeContextCurrent alcMakeContextCurrent
#define palcProcessContext alcProcessContext
#define palcSuspendContext alcSuspendContext
#define palcDestroyContext alcDestroyContext
#define palcGetCurrentContext alcGetCurrentContext
#define palcGetContextsDevice alcGetContextsDevice
#define palcOpenDevice alcOpenDevice
#define palcCloseDevice alcCloseDevice
#define palcGetError alcGetError
#define palcIsExtensionPresent alcIsExtensionPresent
#define palcGetProcAddress alcGetProcAddress
#define palcGetEnumValue alcGetEnumValue
#define palcGetString alcGetString
#define palcGetIntegerv alcGetIntegerv
#define palcCaptureOpenDevice alcCaptureOpenDevice
#define palcCaptureCloseDevice alcCaptureCloseDevice
#define palcCaptureStart alcCaptureStart
#define palcCaptureStop alcCaptureStop
#define palcCaptureSamples alcCaptureSamples
#define palEnable alEnable
#define palDisable alDisable
#define palIsEnabled alIsEnabled
#define palGetString alGetString
#define palGetBooleanv alGetBooleanv
#define palGetIntegerv alGetIntegerv
#define palGetFloatv alGetFloatv
#define palGetDoublev alGetDoublev
#define palGetBoolean alGetBoolean
#define palGetInteger alGetInteger
#define palGetFloat alGetFloat
#define palGetDouble alGetDouble
#define palGetError alGetError
#define palIsExtensionPresent alIsExtensionPresent
#define palGetProcAddress alGetProcAddress
#define palGetEnumValue alGetEnumValue
#define palListenerf alListenerf
#define palListener3f alListener3f
#define palListenerfv alListenerfv
#define palListeneri alListeneri
#define palListener3i alListener3i
#define palListeneriv alListeneriv
#define palGetListenerf alGetListenerf
#define palGetListener3f alGetListener3f
#define palGetListenerfv alGetListenerfv
#define palGetListeneri alGetListeneri
#define palGetListener3i alGetListener3i
#define palGetListeneriv alGetListeneriv
#define palGenSources alGenSources
#define palDeleteSources alDeleteSources
#define palIsSource alIsSource
#define palSourcef alSourcef
#define palSource3f alSource3f
#define palSourcefv alSourcefv
#define palSourcei alSourcei
#define palSource3i alSource3i
#define palSourceiv alSourceiv
#define palGetSourcef alGetSourcef
#define palGetSource3f alGetSource3f
#define palGetSourcefv alGetSourcefv
#define palGetSourcei alGetSourcei
#define palGetSource3i alGetSource3i
#define palGetSourceiv alGetSourceiv
#define palSourcePlayv alSourcePlayv
#define palSourceStopv alSourceStopv
#define palSourceRewindv alSourceRewindv
#define palSourcePausev alSourcePausev
#define palSourcePlay alSourcePlay
#define palSourceStop alSourceStop
#define palSourceRewind alSourceRewind
#define palSourcePause alSourcePause
#define palSourceQueueBuffers alSourceQueueBuffers
#define palSourceUnqueueBuffers alSourceUnqueueBuffers
#define palGenBuffers alGenBuffers
#define palDeleteBuffers alDeleteBuffers
#define palIsBuffer alIsBuffer
#define palBufferf alBufferf
#define palBuffer3f alBuffer3f
#define palBufferfv alBufferfv
#define palBufferi alBufferi
#define palBuffer3i alBuffer3i
#define palBufferiv alBufferiv
#define palGetBufferf alGetBufferf
#define palGetBuffer3f alGetBuffer3f
#define palGetBufferfv alGetBufferfv
#define palGetBufferi alGetBufferi
#define palGetBuffer3i alGetBuffer3i
#define palGetBufferiv alGetBufferiv
#define palBufferData alBufferData
#define palDopplerFactor alDopplerFactor
#define palDopplerVelocity alDopplerVelocity
#define palDistanceModel alDistanceModel
#define palSpeedOfSound alSpeedOfSound
#endif
/* OpenAL only allows for 1 single access to the device at the same time */
extern CRITICAL_SECTION openal_crst;
extern int local_contexts;
extern typeof(alcGetCurrentContext) *get_context;
extern typeof(alcMakeContextCurrent) *set_context;
#define getALError() \
do { \
ALenum err = palGetError(); \
if(err != AL_NO_ERROR) \
{ \
ERR(">>>>>>>>>>>> Received AL error %#x on context %p, %s:%u\n", err, get_context(), __FUNCTION__, __LINE__); \
} \
} while (0)
#define getALCError(dev) \
do { \
ALenum err = palcGetError(dev); \
if(err != ALC_NO_ERROR) \
{ \
ERR(">>>>>>>>>>>> Received ALC error %#x on device %p, %s:%u\n", err, dev, __FUNCTION__, __LINE__); \
} \
} while(0)
#define setALContext(actx) \
do { \
ALCcontext *__old_ctx, *cur_ctx = actx ; \
if (!local_contexts) EnterCriticalSection(&openal_crst); \
__old_ctx = get_context(); \
if (__old_ctx != cur_ctx && set_context(cur_ctx) == ALC_FALSE) {\
ERR("Couldn't set current context!!\n"); \
getALCError(palcGetContextsDevice(cur_ctx)); \
}
/* Only restore a NULL context if using global contexts, for TLS contexts always restore */
#define popALContext() \
if (__old_ctx != cur_ctx \
&& (local_contexts || __old_ctx) \
&& set_context(__old_ctx) == ALC_FALSE) { \
ERR("Couldn't restore old context!!\n"); \
getALCError(palcGetContextsDevice(__old_ctx)); \
} \
if (!local_contexts) LeaveCriticalSection(&openal_crst); \
} while (0)
#endif