From 4b95f0f33ac155a84c42c73b2d00547e3983e133 Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Sun, 13 May 2007 21:19:57 -0700
Subject: [PATCH] Add OpenAL32 DLL thunk

---
 Makefile.in                 |    2 +
 configure.ac                |   15 ++
 dlls/Makefile.in            |    1 +
 dlls/openal32/Makefile.in   |   14 ++
 dlls/openal32/openal.c      |  418 +++++++++++++++++++++++++++++++++++++++++++
 dlls/openal32/openal32.spec |   97 ++++++++++
 include/config.h.in         |    6 +
 7 files changed, 553 insertions(+), 0 deletions(-)
 create mode 100644 dlls/openal32/Makefile.in
 create mode 100644 dlls/openal32/openal.c
 create mode 100644 dlls/openal32/openal32.spec

diff --git a/Makefile.in b/Makefile.in
index 30e0581..7d834b7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -322,6 +322,7 @@ ALL_MAKEFILES = \
 	dlls/oledlg/Makefile \
 	dlls/olepro32/Makefile \
 	dlls/olesvr32/Makefile \
+	dlls/openal32/Makefile \
 	dlls/opengl32/Makefile \
 	dlls/powrprof/Makefile \
 	dlls/psapi/Makefile \
@@ -668,6 +669,7 @@ dlls/olecli32/Makefile: dlls/olecli32/Makefile.in dlls/Makedll.rules
 dlls/oledlg/Makefile: dlls/oledlg/Makefile.in dlls/Makedll.rules
 dlls/olepro32/Makefile: dlls/olepro32/Makefile.in dlls/Makedll.rules
 dlls/olesvr32/Makefile: dlls/olesvr32/Makefile.in dlls/Makedll.rules
+dlls/openal32/Makefile: dlls/openal32/Makefile.in dlls/Makedll.rules
 dlls/opengl32/Makefile: dlls/opengl32/Makefile.in dlls/Makedll.rules
 dlls/powrprof/Makefile: dlls/powrprof/Makefile.in dlls/Makedll.rules
 dlls/psapi/Makefile: dlls/psapi/Makefile.in dlls/Makedll.rules
diff --git a/configure.ac b/configure.ac
index 52323c7..d87fe69 100644
--- a/configure.ac
+++ b/configure.ac
@@ -157,6 +157,8 @@ AC_SUBST(QUARTZFILES,"")
 dnl **** Check for header files ****
 
 AC_CHECK_HEADERS(\
+	OpenAL/al.h \
+	AL/al.h \
 	AudioUnit/AudioUnit.h \
 	Carbon/Carbon.h \
 	CoreAudio/CoreAudio.h \
@@ -839,6 +841,14 @@ then
     AC_CHECK_LIB(capi20,capi20_register,[AC_DEFINE(HAVE_CAPI4LINUX,1,[Define if you have capi4linux libs and headers])])
 fi
 
+dnl **** Check for OpenAL support ****
+dnl **** Mac OSX OpenAL support checked below ****
+
+if test "$ac_cv_header_AL_al_h" = "yes"
+	then
+	dnl OpenAL framework
+fi
+
 dnl **** Check for gcc specific options ****
 
 AC_SUBST(EXTRACFLAGS,"")
@@ -991,6 +1001,10 @@ case $host_os in
         dnl CoreServices needed by AudioUnit
         AC_SUBST(COREAUDIO,"-framework CoreAudio -framework AudioUnit -framework CoreServices -framework AudioToolbox -framework CoreMIDI")
     fi
+	if test "$ac_cv_header_OpenAL_al_h" = "yes"
+	then
+		dnl OpenAL framework
+	fi
     case $host_cpu in
       *powerpc*)
         LDDLLFLAGS="$LDDLLFLAGS -read_only_relocs warning"  dnl FIXME
@@ -1652,6 +1666,7 @@ AC_CONFIG_FILES([dlls/olecli32/Makefile])
 AC_CONFIG_FILES([dlls/oledlg/Makefile])
 AC_CONFIG_FILES([dlls/olepro32/Makefile])
 AC_CONFIG_FILES([dlls/olesvr32/Makefile])
+AC_CONFIG_FILES([dlls/openal32/Makefile])
 AC_CONFIG_FILES([dlls/opengl32/Makefile])
 AC_CONFIG_FILES([dlls/powrprof/Makefile])
 AC_CONFIG_FILES([dlls/psapi/Makefile])
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index f9707e7..6741978 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -138,6 +138,7 @@ BASEDIRS = \
 	oledlg \
 	olepro32 \
 	olesvr32 \
+	openal32 \
 	powrprof \
 	psapi \
 	pstorec \
diff --git a/dlls/openal32/Makefile.in b/dlls/openal32/Makefile.in
new file mode 100644
index 0000000..a30042b
--- /dev/null
+++ b/dlls/openal32/Makefile.in
@@ -0,0 +1,14 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = openal32.dll
+IMPORTS   = kernel32 ntdll
+EXTRALIBS = -ldl
+
+C_SRCS = \
+	openal.c
+
+@MAKE_DLL_RULES@
+
+@DEPENDENCIES@  # everything below this line is overwritten by make depend
diff --git a/dlls/openal32/openal.c b/dlls/openal32/openal.c
new file mode 100644
index 0000000..e324833
--- /dev/null
+++ b/dlls/openal32/openal.c
@@ -0,0 +1,418 @@
+/*
+ * OpenAL32.dll thunk. Wraps Win32 OpenAL function calls around a native
+ * implementation.
+ *
+ * Copyright 2007 Nick Burns (adger44@hotmail.com)
+ * Copyright 2007 Chris Robinson
+ *
+ * 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
+ */
+
+#include "config.h"
+
+#if !defined(HAVE_OPENAL_AL_H) && !defined(HAVE_AL_AL_H)
+
+#error You need OpenAL installed to build this DLL!
+
+#else
+
+#include <stdarg.h>
+#include <assert.h>
+#include <dlfcn.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wine/debug.h"
+
+#if defined(HAVE_OPENAL_AL_H)
+    #include <OpenAL/al.h>
+    #include <OpenAL/alc.h>
+#elif defined(HAVE_AL_AL_H)
+    #include <AL/al.h>
+    #include <AL/alc.h>
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(openal);
+
+
+static HMODULE openal32_handle;
+static void *openal_dl;
+
+#ifdef __APPLE__
+#define OPENAL_LIBNAME "libopenal.dynlib"
+#else
+#define OPENAL_LIBNAME "libopenal.so"
+#endif
+
+/* Make the thunking functions */
+
+/* NOTE: If you add a function here, you *must* also make sure to load it in
+ * load_procs!
+ */
+
+#define MAKE_PROC(ret, name, params, args) \
+typedef ret (AL_APIENTRY * t_##name)params; \
+static t_##name p_##name = NULL; \
+ret CDECL wine_##name params \
+{ \
+    TRACE(#name " == %p\n", p_##name); \
+    assert(p_##name); \
+    return p_##name args; \
+}
+
+/* OpenAL ALC 1.0 functions */
+MAKE_PROC(ALCcontext*   , alcCreateContext, ( ALCdevice *device, const ALCint* attrlist ), ( device, attrlist ))
+MAKE_PROC(ALCboolean    , alcMakeContextCurrent, ( ALCcontext *context ), ( context ))
+MAKE_PROC(ALvoid        , alcProcessContext, ( ALCcontext *context ), ( context ))
+MAKE_PROC(ALvoid        , alcSuspendContext, ( ALCcontext *context ), ( context ))
+MAKE_PROC(ALvoid        , alcDestroyContext, ( ALCcontext *context ), ( context ))
+MAKE_PROC(ALCcontext*   , alcGetCurrentContext, ( ALCvoid ), (  ))
+MAKE_PROC(ALCdevice*    , alcGetContextsDevice, ( ALCcontext *context ), ( context ))
+MAKE_PROC(ALCdevice*    , alcOpenDevice, ( const ALCchar *devicename ), ( devicename ))
+MAKE_PROC(ALCboolean    , alcCloseDevice, ( ALCdevice *device ), ( device ))
+MAKE_PROC(ALCenum       , alcGetError, ( ALCdevice *device ), ( device ))
+MAKE_PROC(ALCboolean    , alcIsExtensionPresent, ( ALCdevice *device, const ALCchar *extname ), ( device, extname ))
+MAKE_PROC(ALCenum       , alcGetEnumValue, ( ALCdevice *device, const ALCchar *enumname ), ( device, enumname ))
+MAKE_PROC(const ALCchar*, alcGetString, ( ALCdevice *device, ALCenum param ), ( device, param ))
+MAKE_PROC(ALvoid        , alcGetIntegerv, ( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest ), ( device, param, size, dest ))
+
+/* OpenAL 1.0 functions */
+MAKE_PROC(ALvoid       , alEnable, ( ALenum capability ), ( capability ))
+MAKE_PROC(ALvoid       , alDisable, ( ALenum capability ), ( capability ))
+MAKE_PROC(ALboolean    , alIsEnabled, ( ALenum capability ), ( capability ))
+MAKE_PROC(const ALchar*, alGetString, ( ALenum param ), ( param ))
+MAKE_PROC(ALvoid       , alGetBooleanv, ( ALenum param, ALboolean* data ), ( param, data ))
+MAKE_PROC(ALvoid       , alGetIntegerv, ( ALenum param, ALint* data ), ( param, data ))
+MAKE_PROC(ALvoid       , alGetFloatv, ( ALenum param, ALfloat* data ), ( param, data ))
+MAKE_PROC(ALvoid       , alGetDoublev, ( ALenum param, ALdouble* data ), ( param, data ))
+MAKE_PROC(ALboolean    , alGetBoolean, ( ALenum param ), ( param ))
+MAKE_PROC(ALint        , alGetInteger, ( ALenum param ), ( param ))
+MAKE_PROC(ALfloat      , alGetFloat, ( ALenum param ), ( param ))
+MAKE_PROC(ALdouble     , alGetDouble, ( ALenum param ), ( param ))
+MAKE_PROC(ALenum       , alGetError, ( ALvoid ), (  ))
+MAKE_PROC(ALboolean    , alIsExtensionPresent, (const ALchar* extname ), (extname ))
+MAKE_PROC(ALenum       , alGetEnumValue, ( const ALchar* ename ), ( ename ))
+MAKE_PROC(ALvoid       , alListenerf, ( ALenum param, ALfloat value ), ( param, value ))
+MAKE_PROC(ALvoid       , alListener3f, ( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( param, value1, value2, value3 ))
+MAKE_PROC(ALvoid       , alListenerfv, ( ALenum param, const ALfloat* values ), ( param, values ))
+MAKE_PROC(ALvoid       , alListeneri, ( ALenum param, ALint value ), ( param, value ))
+MAKE_PROC(ALvoid       , alGetListenerf, ( ALenum param, ALfloat* value ), ( param, value ))
+MAKE_PROC(ALvoid       , alGetListener3f, ( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ), ( param, value1, value2, value3 ))
+MAKE_PROC(ALvoid       , alGetListenerfv, ( ALenum param, ALfloat* values ), ( param, values ))
+MAKE_PROC(ALvoid       , alGetListeneri, ( ALenum param, ALint* value ), ( param, value ))
+MAKE_PROC(ALvoid       , alGetListeneriv, ( ALenum param, ALint* values ), ( param, values ))
+MAKE_PROC(ALvoid       , alGenSources, ( ALsizei n, ALuint* sources ), ( n, sources ))
+MAKE_PROC(ALvoid       , alDeleteSources, ( ALsizei n, const ALuint* sources ), ( n, sources ))
+MAKE_PROC(ALboolean    , alIsSource, ( ALuint sid ), ( sid ))
+MAKE_PROC(ALvoid       , alSourcef, ( ALuint sid, ALenum param, ALfloat value), ( sid, param, value))
+MAKE_PROC(ALvoid       , alSource3f, ( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( sid, param, value1, value2, value3 ))
+MAKE_PROC(ALvoid       , alSourcefv, ( ALuint sid, ALenum param, const ALfloat* values ), ( sid, param, values ))
+MAKE_PROC(ALvoid       , alSourcei, ( ALuint sid, ALenum param, ALint value), ( sid, param, value))
+MAKE_PROC(ALvoid       , alGetSourcef, ( ALuint sid, ALenum param, ALfloat* value ), ( sid, param, value ))
+MAKE_PROC(ALvoid       , alGetSource3f, ( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3), ( sid, param, value1, value2, value3))
+MAKE_PROC(ALvoid       , alGetSourcefv, ( ALuint sid, ALenum param, ALfloat* values ), ( sid, param, values ))
+MAKE_PROC(ALvoid       , alGetSourcei, ( ALuint sid, ALenum param, ALint* value ), ( sid, param, value ))
+MAKE_PROC(ALvoid       , alGetSourceiv, ( ALuint sid, ALenum param, ALint* values ), ( sid, param, values ))
+MAKE_PROC(ALvoid       , alSourcePlayv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))
+MAKE_PROC(ALvoid       , alSourceStopv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))
+MAKE_PROC(ALvoid       , alSourceRewindv, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))
+MAKE_PROC(ALvoid       , alSourcePausev, ( ALsizei ns, const ALuint *sids ), ( ns, sids ))
+MAKE_PROC(ALvoid       , alSourcePlay, ( ALuint sid ), ( sid ))
+MAKE_PROC(ALvoid       , alSourceStop, ( ALuint sid ), ( sid ))
+MAKE_PROC(ALvoid       , alSourceRewind, ( ALuint sid ), ( sid ))
+MAKE_PROC(ALvoid       , alSourcePause, ( ALuint sid ), ( sid ))
+MAKE_PROC(ALvoid       , alSourceQueueBuffers, ( ALuint sid, ALsizei numEntries, const ALuint *bids ), ( sid, numEntries, bids ))
+MAKE_PROC(ALvoid       , alSourceUnqueueBuffers, ( ALuint sid, ALsizei numEntries, ALuint *bids ), ( sid, numEntries, bids ))
+MAKE_PROC(ALvoid       , alGenBuffers, ( ALsizei n, ALuint* buffers ), ( n, buffers ))
+MAKE_PROC(ALvoid       , alDeleteBuffers, ( ALsizei n, const ALuint* buffers ), ( n, buffers ))
+MAKE_PROC(ALboolean    , alIsBuffer, ( ALuint bid ), ( bid ))
+MAKE_PROC(ALvoid       , alBufferData, ( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ), ( bid, format, data, size, freq ))
+MAKE_PROC(ALvoid       , alGetBufferf, ( ALuint bid, ALenum param, ALfloat* value ), ( bid, param, value ))
+MAKE_PROC(ALvoid       , alGetBufferfv, ( ALuint bid, ALenum param, ALfloat* values ), ( bid, param, values ))
+MAKE_PROC(ALvoid       , alGetBufferi, ( ALuint bid, ALenum param, ALint* value ), ( bid, param, value ))
+MAKE_PROC(ALvoid       , alGetBufferiv, ( ALuint bid, ALenum param, ALint* values ), ( bid, param, values ))
+MAKE_PROC(ALvoid       , alDopplerFactor, ( ALfloat value ), ( value ))
+MAKE_PROC(ALvoid       , alDopplerVelocity, ( ALfloat value ), ( value ))
+MAKE_PROC(ALvoid       , alDistanceModel, ( ALenum distanceModel ), ( distanceModel ))
+
+/* OpenAL ALC 1.1 functions */
+MAKE_PROC(ALCdevice*, alcCaptureOpenDevice, ( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ), ( devicename, frequency, format, buffersize ))
+MAKE_PROC(ALCboolean, alcCaptureCloseDevice, ( ALCdevice *device ), ( device ))
+MAKE_PROC(ALvoid    , alcCaptureStart, ( ALCdevice *device ), ( device ))
+MAKE_PROC(ALvoid    , alcCaptureStop, ( ALCdevice *device ), ( device ))
+MAKE_PROC(ALvoid    , alcCaptureSamples, ( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ), ( device, buffer, samples ))
+
+/* OpenAL 1.1 functions */
+MAKE_PROC(ALvoid, alListener3i, ( ALenum param, ALint value1, ALint value2, ALint value3 ), ( param, value1, value2, value3 ))
+MAKE_PROC(ALvoid, alListeneriv, ( ALenum param, const ALint* values ), ( param, values ))
+MAKE_PROC(ALvoid, alGetListener3i, ( ALenum param, ALint *value1, ALint *value2, ALint *value3 ), ( param, value1, value2, value3 ))
+MAKE_PROC(ALvoid, alSource3i, ( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ), ( sid, param, value1, value2, value3 ))
+MAKE_PROC(ALvoid, alSourceiv, ( ALuint sid, ALenum param, const ALint* values ), ( sid, param, values ))
+MAKE_PROC(ALvoid, alGetSource3i, ( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3), ( sid, param, value1, value2, value3))
+MAKE_PROC(ALvoid, alBufferf, ( ALuint bid, ALenum param, ALfloat value), ( bid, param, value))
+MAKE_PROC(ALvoid, alBuffer3f, ( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ), ( bid, param, value1, value2, value3 ))
+MAKE_PROC(ALvoid, alBufferfv, ( ALuint bid, ALenum param, const ALfloat* values ), ( bid, param, values ))
+MAKE_PROC(ALvoid, alBufferi, ( ALuint bid, ALenum param, ALint value), ( bid, param, value))
+MAKE_PROC(ALvoid, alBuffer3i, ( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ), ( bid, param, value1, value2, value3 ))
+MAKE_PROC(ALvoid, alBufferiv, ( ALuint bid, ALenum param, const ALint* values ), ( bid, param, values ))
+MAKE_PROC(ALvoid, alGetBuffer3f, ( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3), ( bid, param, value1, value2, value3))
+MAKE_PROC(ALvoid, alGetBuffer3i, ( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3), ( bid, param, value1, value2, value3))
+MAKE_PROC(ALvoid, alSpeedOfSound, ( ALfloat value ), ( value ))
+
+/* ALC_LOKI_audio_channel */
+MAKE_PROC(ALCfloat, alcGetAudioChannel_LOKI, ( ALCuint channel ), ( channel ))
+MAKE_PROC(ALCvoid , alcSetAudioChannel_LOKI, ( ALCuint channel, ALCfloat volume ), ( channel, volume ))
+
+/* AL_LOKI_buffer_data_callback */
+MAKE_PROC(ALvoid, alBufferDataWithCallback_LOKI, ( ALuint bid, ALint (*callback)(ALuint,ALuint,ALvoid*,ALenum,ALuint) ), ( bid, callback ))
+
+/* ALC_EXT_MAC_OSX */
+MAKE_PROC(ALvoid  , alcMacOSXRenderingQualityProcPtr, ( const ALint value ), ( value ))
+MAKE_PROC(ALvoid  , alMacOSXRenderChannelCountProcPtr, ( const ALint value ), ( value ))
+MAKE_PROC(ALvoid  , alcMacOSXMixerMaxiumumBussesProcPtr, ( const ALint value ), ( value ))
+MAKE_PROC(ALvoid  , alcMacOSXMixerOutputRateProcPtr, ( const ALdouble value ), ( value ))
+MAKE_PROC(ALint   , alcMacOSXGetRenderingQualityProcPtr, ( ALCvoid ), (  ))
+MAKE_PROC(ALint   , alMacOSXGetRenderChannelCountProcPtr, ( ALvoid ), (  ))
+MAKE_PROC(ALint   , alcMacOSXGetMixerMaxiumumBussesProcPtr, ( ALCvoid ), (  ))
+MAKE_PROC(ALdouble, alcMacOSXGetMixerOutputRateProcPtr, ( ALCvoid ), (  ))
+
+/* ALC_EXT_ASA */
+MAKE_PROC(ALenum, alcASAGetSourceProcPtr, ( const ALuint property, ALuint source, ALvoid *data, ALuint* dataSize ), ( property, source, data, dataSize ))
+MAKE_PROC(ALenum, alcASASetSourceProcPtr, ( const ALuint property, ALuint source, ALvoid *data, ALuint dataSize ), ( property, source, data, dataSize ))
+MAKE_PROC(ALenum, alcASAGetListenerProcPtr, ( const ALuint property, ALvoid *data,ALuint* dataSize ), ( property, data, dataSize ))
+MAKE_PROC(ALenum, alcASASetListenerProcPtr, ( const ALuint property, ALvoid *data,ALuint dataSize ), ( property, data, dataSize ))
+
+/* AL_EXT_STATIC_BUFFER */
+MAKE_PROC(ALvoid, alBufferDataStatic, ( const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq ), ( bid, format, data, size, freq ))
+
+#undef MAKE_PROC
+
+/* These are handled seperately */
+typedef void* (AL_APIENTRY * t_alcGetProcAddress)(ALCdevice *device, const ALCchar *funcname);
+static t_alcGetProcAddress p_alcGetProcAddress = NULL;
+void* CDECL wine_alcGetProcAddress(ALCdevice *device, const ALCchar *funcname)
+{
+    void *ret = NULL;
+
+    /* Check to make sure the native implementation has the function before
+     * returning the thunk
+     */
+    TRACE("alcGetProcAddress == %p\n", p_alcGetProcAddress);
+    assert(p_alcGetProcAddress);
+    if(p_alcGetProcAddress(device, funcname))
+        ret = GetProcAddress(openal32_handle, funcname);
+
+    TRACE("funcname == %s, ret == %p\n", funcname, ret);
+    return ret;
+}
+
+typedef void* (AL_APIENTRY * t_alGetProcAddress)(const ALchar *funcname);
+static t_alGetProcAddress p_alGetProcAddress = NULL;
+void* CDECL wine_alGetProcAddress(const ALchar* funcname)
+{
+    void *ret = NULL;
+
+    TRACE("alGetProcAddress == %p\n", p_alGetProcAddress);
+    assert(p_alGetProcAddress);
+    if(p_alGetProcAddress(funcname))
+        ret = GetProcAddress(openal32_handle, funcname);
+
+    TRACE("funcname == %s, ret == %p\n", funcname, ret);
+    return ret;
+}
+
+
+static BOOL load_procs(void)
+{
+    char *err;
+
+    openal_dl = dlopen(OPENAL_LIBNAME, RTLD_LAZY);
+    if(!openal_dl)
+    {
+        ERR("Could not load " OPENAL_LIBNAME ": %s\n", dlerror());
+        return FALSE;
+    }
+
+    /* Clear error status */
+    dlerror();
+
+/* OpenAL 1.1 is required (since that is what's exported). Unix (Linux,
+ * FreeBSD, etc), Windows, and OSX all support this version.
+ */
+#define LOAD_SYM(sym) \
+p_##sym = dlsym(openal_dl, #sym); \
+if((err=dlerror()) != NULL) { \
+    ERR("Could not load required function " #sym ": %s\n", err); \
+    dlclose(openal_dl); \
+    openal_dl = NULL; \
+    return FALSE; \
+}
+
+LOAD_SYM(alcCreateContext);
+LOAD_SYM(alcMakeContextCurrent);
+LOAD_SYM(alcProcessContext);
+LOAD_SYM(alcSuspendContext);
+LOAD_SYM(alcDestroyContext);
+LOAD_SYM(alcGetCurrentContext);
+LOAD_SYM(alcGetContextsDevice);
+LOAD_SYM(alcOpenDevice);
+LOAD_SYM(alcCloseDevice);
+LOAD_SYM(alcGetError);
+LOAD_SYM(alcIsExtensionPresent);
+LOAD_SYM(alcGetProcAddress);
+LOAD_SYM(alcGetEnumValue);
+LOAD_SYM(alcGetString);
+LOAD_SYM(alcGetIntegerv);
+
+LOAD_SYM(alEnable);
+LOAD_SYM(alDisable);
+LOAD_SYM(alIsEnabled);
+LOAD_SYM(alGetString);
+LOAD_SYM(alGetBooleanv);
+LOAD_SYM(alGetIntegerv);
+LOAD_SYM(alGetFloatv);
+LOAD_SYM(alGetDoublev);
+LOAD_SYM(alGetBoolean);
+LOAD_SYM(alGetInteger);
+LOAD_SYM(alGetFloat);
+LOAD_SYM(alGetDouble);
+LOAD_SYM(alGetError);
+LOAD_SYM(alIsExtensionPresent);
+LOAD_SYM(alGetProcAddress);
+LOAD_SYM(alGetEnumValue);
+LOAD_SYM(alListenerf);
+LOAD_SYM(alListener3f);
+LOAD_SYM(alListenerfv);
+LOAD_SYM(alListeneri);
+LOAD_SYM(alGetListenerf);
+LOAD_SYM(alGetListener3f);
+LOAD_SYM(alGetListenerfv);
+LOAD_SYM(alGetListeneri);
+LOAD_SYM(alGetListeneriv);
+LOAD_SYM(alGenSources);
+LOAD_SYM(alDeleteSources);
+LOAD_SYM(alIsSource);
+LOAD_SYM(alSourcef);
+LOAD_SYM(alSource3f);
+LOAD_SYM(alSourcefv);
+LOAD_SYM(alSourcei);
+LOAD_SYM(alGetSourcef);
+LOAD_SYM(alGetSource3f);
+LOAD_SYM(alGetSourcefv);
+LOAD_SYM(alGetSourcei);
+LOAD_SYM(alGetSourceiv);
+LOAD_SYM(alSourcePlayv);
+LOAD_SYM(alSourceStopv);
+LOAD_SYM(alSourceRewindv);
+LOAD_SYM(alSourcePausev);
+LOAD_SYM(alSourcePlay);
+LOAD_SYM(alSourceStop);
+LOAD_SYM(alSourceRewind);
+LOAD_SYM(alSourcePause);
+LOAD_SYM(alSourceQueueBuffers);
+LOAD_SYM(alSourceUnqueueBuffers);
+LOAD_SYM(alGenBuffers);
+LOAD_SYM(alDeleteBuffers);
+LOAD_SYM(alIsBuffer);
+LOAD_SYM(alBufferData);
+LOAD_SYM(alGetBufferf);
+LOAD_SYM(alGetBufferfv);
+LOAD_SYM(alGetBufferi);
+LOAD_SYM(alGetBufferiv);
+LOAD_SYM(alDopplerFactor);
+LOAD_SYM(alDopplerVelocity);
+LOAD_SYM(alDistanceModel);
+
+LOAD_SYM(alcCaptureOpenDevice);
+LOAD_SYM(alcCaptureCloseDevice);
+LOAD_SYM(alcCaptureStart);
+LOAD_SYM(alcCaptureStop);
+LOAD_SYM(alcCaptureSamples);
+
+LOAD_SYM(alListener3i);
+LOAD_SYM(alListeneriv);
+LOAD_SYM(alGetListener3i);
+LOAD_SYM(alSource3i);
+LOAD_SYM(alSourceiv);
+LOAD_SYM(alGetSource3i);
+LOAD_SYM(alBufferf);
+LOAD_SYM(alBuffer3f);
+LOAD_SYM(alBufferfv);
+LOAD_SYM(alBufferi);
+LOAD_SYM(alBuffer3i);
+LOAD_SYM(alBufferiv);
+LOAD_SYM(alGetBuffer3f);
+LOAD_SYM(alGetBuffer3i);
+LOAD_SYM(alSpeedOfSound);
+
+/* Extensions are optional */
+#undef LOAD_SYM
+#define LOAD_SYM(sym) \
+p_##sym = dlsym(openal_dl, #sym); \
+if((err=dlerror()) != NULL) \
+    WARN("Could not load function " #sym ": %s\n", err)
+
+LOAD_SYM(alcGetAudioChannel_LOKI);
+LOAD_SYM(alcSetAudioChannel_LOKI);
+
+LOAD_SYM(alBufferDataWithCallback_LOKI);
+
+LOAD_SYM(alcMacOSXRenderingQualityProcPtr);
+LOAD_SYM(alMacOSXRenderChannelCountProcPtr);
+LOAD_SYM(alcMacOSXMixerMaxiumumBussesProcPtr);
+LOAD_SYM(alcMacOSXMixerOutputRateProcPtr);
+LOAD_SYM(alcMacOSXGetRenderingQualityProcPtr);
+LOAD_SYM(alMacOSXGetRenderChannelCountProcPtr);
+LOAD_SYM(alcMacOSXGetMixerMaxiumumBussesProcPtr);
+LOAD_SYM(alcMacOSXGetMixerOutputRateProcPtr);
+
+LOAD_SYM(alcASAGetSourceProcPtr);
+LOAD_SYM(alcASASetSourceProcPtr);
+LOAD_SYM(alcASAGetListenerProcPtr);
+LOAD_SYM(alcASASetListenerProcPtr);
+
+LOAD_SYM(alBufferDataStatic);
+
+#undef LOAD_SYM
+
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           OpenAL initialisation routine
+ */
+BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
+{
+    BOOL ret = TRUE;
+
+    switch(reason)
+    {
+        case DLL_PROCESS_ATTACH:
+            ret = load_procs();
+            if(ret != FALSE)
+                openal32_handle = hinst;
+            break;
+        case DLL_PROCESS_DETACH:
+            if(openal_dl)
+                dlclose(openal_dl);
+            break;
+    }
+
+    return ret;
+}
+
+
+#endif /* defined(HAVE_OPENAL_AL_H) || defined(HAVE_AL_AL_H) */
diff --git a/dlls/openal32/openal32.spec b/dlls/openal32/openal32.spec
new file mode 100644
index 0000000..df76e3a
--- /dev/null
+++ b/dlls/openal32/openal32.spec
@@ -0,0 +1,97 @@
+#OpenAL ALC_1_0
+@ cdecl alcCreateContext(ptr ptr ) wine_alcCreateContext
+@ cdecl alcMakeContextCurrent(ptr) wine_alcMakeContextCurrent
+@ cdecl alcProcessContext(ptr) wine_alcProcessContext
+@ cdecl alcSuspendContext(ptr) wine_alcSuspendContext
+@ cdecl alcDestroyContext(ptr) wine_alcDestroyContext
+@ cdecl alcGetCurrentContext( ) wine_alcGetCurrentContext
+@ cdecl alcGetContextsDevice(ptr) wine_alcGetContextsDevice
+@ cdecl alcOpenDevice(str) wine_alcOpenDevice
+@ cdecl alcCloseDevice(ptr) wine_alcCloseDevice
+@ cdecl alcGetError(ptr) wine_alcGetError
+@ cdecl alcIsExtensionPresent(ptr str) wine_alcIsExtensionPresent
+@ cdecl alcGetProcAddress(ptr str) wine_alcGetProcAddress
+@ cdecl alcGetEnumValue(ptr str) wine_alcGetEnumValue
+@ cdecl alcGetString(ptr long ) wine_alcGetString
+@ cdecl alcGetIntegerv(ptr long  long  ptr) wine_alcGetIntegerv
+#OpenAL AL_1_0
+@ cdecl alEnable(long ) wine_alEnable
+@ cdecl alDisable(long ) wine_alDisable
+@ cdecl alIsEnabled(long ) wine_alIsEnabled
+@ cdecl alGetString(long ) wine_alGetString
+@ cdecl alGetBooleanv(long  ptr ) wine_alGetBooleanv
+@ cdecl alGetIntegerv(long  ptr ) wine_alGetIntegerv
+@ cdecl alGetFloatv(long  ptr ) wine_alGetFloatv
+@ cdecl alGetDoublev(long  ptr ) wine_alGetDoublev
+@ cdecl alGetBoolean(long ) wine_alGetBoolean
+@ cdecl alGetInteger(long ) wine_alGetInteger
+@ cdecl alGetFloat(long ) wine_alGetFloat
+@ cdecl alGetDouble(long ) wine_alGetDouble
+@ cdecl alGetError( ) wine_alGetError
+@ cdecl alIsExtensionPresent(str ) wine_alIsExtensionPresent
+@ cdecl alGetProcAddress(str ) wine_alGetProcAddress
+@ cdecl alGetEnumValue(str ) wine_alGetEnumValue
+@ cdecl alListenerf(long  long ) wine_alListenerf
+@ cdecl alListener3f(long  long  long  long ) wine_alListener3f
+@ cdecl alListenerfv(long  ptr ) wine_alListenerfv
+@ cdecl alListeneri(long  long ) wine_alListeneri
+@ cdecl alGetListenerf(long  ptr ) wine_alGetListenerf
+@ cdecl alGetListener3f(long  ptr ptr ptr) wine_alGetListener3f
+@ cdecl alGetListenerfv(long  ptr ) wine_alGetListenerfv
+@ cdecl alGetListeneri(long  ptr ) wine_alGetListeneri
+@ cdecl alGetListeneriv(long  ptr ) wine_alGetListeneriv
+@ cdecl alGenSources(long  ptr ) wine_alGenSources
+@ cdecl alDeleteSources(long  ptr ) wine_alDeleteSources
+@ cdecl alIsSource(long ) wine_alIsSource
+@ cdecl alSourcef(long  long  long ) wine_alSourcef
+@ cdecl alSource3f(long  long  long  long  long ) wine_alSource3f
+@ cdecl alSourcefv(long  long  ptr ) wine_alSourcefv
+@ cdecl alSourcei(long  long  long ) wine_alSourcei
+@ cdecl alGetSourcef(long  long  ptr ) wine_alGetSourcef
+@ cdecl alGetSource3f(long  long  ptr  ptr  ptr ) wine_alGetSource3f
+@ cdecl alGetSourcefv(long  long  ptr ) wine_alGetSourcefv
+@ cdecl alGetSourcei(long  long  ptr ) wine_alGetSourcei
+@ cdecl alGetSourceiv(long  long  ptr ) wine_alGetSourceiv
+@ cdecl alSourcePlayv(long  ptr) wine_alSourcePlayv
+@ cdecl alSourceStopv(long  ptr) wine_alSourceStopv
+@ cdecl alSourceRewindv(long  ptr) wine_alSourceRewindv
+@ cdecl alSourcePausev(long  ptr) wine_alSourcePausev
+@ cdecl alSourcePlay(long ) wine_alSourcePlay
+@ cdecl alSourceStop(long ) wine_alSourceStop
+@ cdecl alSourceRewind(long ) wine_alSourceRewind
+@ cdecl alSourcePause(long ) wine_alSourcePause
+@ cdecl alSourceQueueBuffers(long  long  ptr) wine_alSourceQueueBuffers
+@ cdecl alSourceUnqueueBuffers(long  long  ptr) wine_alSourceUnqueueBuffers
+@ cdecl alGenBuffers(long  ptr ) wine_alGenBuffers
+@ cdecl alDeleteBuffers(long  ptr ) wine_alDeleteBuffers
+@ cdecl alIsBuffer(long ) wine_alIsBuffer
+@ cdecl alBufferData(long  long  ptr  long  long ) wine_alBufferData
+@ cdecl alGetBufferf(long  long  ptr ) wine_alGetBufferf
+@ cdecl alGetBufferfv(long  long  ptr ) wine_alGetBufferfv
+@ cdecl alGetBufferi(long  long  ptr ) wine_alGetBufferi
+@ cdecl alGetBufferiv(long  long  ptr ) wine_alGetBufferiv
+@ cdecl alDopplerFactor(long ) wine_alDopplerFactor
+@ cdecl alDopplerVelocity(long ) wine_alDopplerVelocity
+@ cdecl alDistanceModel(long ) wine_alDistanceModel
+#OpenAL ALC_1_1
+@ cdecl alcCaptureOpenDevice(str long  long  long ) wine_alcCaptureOpenDevice
+@ cdecl alcCaptureCloseDevice(ptr) wine_alcCaptureCloseDevice
+@ cdecl alcCaptureStart(ptr) wine_alcCaptureStart
+@ cdecl alcCaptureStop(ptr) wine_alcCaptureStop
+@ cdecl alcCaptureSamples(ptr ptr long ) wine_alcCaptureSamples
+#OpenAL AL_1_1
+@ cdecl alListener3i(long  long  long  long ) wine_alListener3i
+@ cdecl alListeneriv(long  ptr ) wine_alListeneriv
+@ cdecl alGetListener3i(long  ptr ptr ptr) wine_alGetListener3i
+@ cdecl alSource3i(long  long  long  long  long ) wine_alSource3i
+@ cdecl alSourceiv(long  long  ptr ) wine_alSourceiv
+@ cdecl alGetSource3i(long  long  ptr  ptr  ptr ) wine_alGetSource3i
+@ cdecl alBufferf(long  long  long ) wine_alBufferf
+@ cdecl alBuffer3f(long  long  long  long  long ) wine_alBuffer3f
+@ cdecl alBufferfv(long  long  ptr ) wine_alBufferfv
+@ cdecl alBufferi(long  long  long ) wine_alBufferi
+@ cdecl alBuffer3i(long  long  long  long  long ) wine_alBuffer3i
+@ cdecl alBufferiv(long  long  ptr ) wine_alBufferiv
+@ cdecl alGetBuffer3f(long  long  ptr  ptr  ptr ) wine_alGetBuffer3f
+@ cdecl alGetBuffer3i(long  long  ptr  ptr  ptr ) wine_alGetBuffer3i
+@ cdecl alSpeedOfSound(long ) wine_alSpeedOfSound
diff --git a/include/config.h.in b/include/config.h.in
index 331e5cc..11fd094 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -11,6 +11,9 @@
 /* Define to 1 if you have the <alsa/asoundlib.h> header file. */
 #undef HAVE_ALSA_ASOUNDLIB_H
 
+/* Define to 1 if you have the <AL/al.h> header file. */
+#undef HAVE_AL_AL_H
+
 /* Define to 1 if you have the <arpa/inet.h> header file. */
 #undef HAVE_ARPA_INET_H
 
@@ -468,6 +471,9 @@
 /* Define to 1 if the system has the type `off_t'. */
 #undef HAVE_OFF_T
 
+/* Define to 1 if you have the <OpenAL/al.h> header file. */
+#undef HAVE_OPENAL_AL_H
+
 /* Define if OpenGL is present on the system */
 #undef HAVE_OPENGL
 
-- 
1.5.0.7

