//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #include "platformX86UNIX/platformX86UNIX.h" #include "console/console.h" #include #include #include #define INITGUID #include // Define the OpenAL and Extension Stub functions #define AL_FUNCTION(fn_return, fn_name, fn_args, fn_value) fn_return stub_##fn_name fn_args{ fn_value } #include #include #include #undef AL_FUNCTION // Declare the OpenAL and Extension Function pointers // And initialize them to the stub functions #define AL_FUNCTION(fn_return,fn_name,fn_args, fn_value) fn_return (*fn_name)fn_args = stub_##fn_name; #include #include #include #undef AL_FUNCTION // Declarations for the "emulated" functions (al functions that don't // exist in the loki openal implementation) ALboolean emu_alGetBoolean(ALenum param); ALint emu_alGetInteger(ALenum param); ALfloat emu_alGetFloat(ALenum param); ALdouble emu_alGetDouble(ALenum param); void emu_alListeneri( ALenum param, ALint value ); void emu_alGetListener3f(ALenum pname,ALfloat *v1,ALfloat *v2,ALfloat *v3); ALCdevice* emu_alcGetContextsDevice(ALCcontext *context); static void *dlHandle = NULL; static char* dlError = "no error"; /*! Get an "emulated" function address and bind it to the function pointer */ static bool bindEmulatedFunction(void *&fnAddress, const char *name) { fnAddress = NULL; if (dStrcmp(name, "alGetBoolean")==0) fnAddress = (void*)&emu_alGetBoolean; else if (dStrcmp(name, "alGetInteger")==0) fnAddress = (void*)&emu_alGetInteger; else if (dStrcmp(name, "alGetFloat")==0) fnAddress = (void*)&emu_alGetFloat; else if (dStrcmp(name, "alGetDouble")==0) fnAddress = (void*)&emu_alGetDouble; else if (dStrcmp(name, "alListeneri")==0) fnAddress = (void*)&emu_alListeneri; else if (dStrcmp(name, "alGetListener3f")==0) fnAddress = (void*)&emu_alGetListener3f; else if (dStrcmp(name, "alcGetContextsDevice")==0) fnAddress = (void*)&emu_alcGetContextsDevice; return fnAddress != NULL; } /*! Get a function address from the OpenAL DLL and bind it to the * function pointer */ static bool bindFunction( void *&fnAddress, const char *name ) { fnAddress = dlsym(dlHandle, name); if( !fnAddress ) if (bindEmulatedFunction(fnAddress, name)) Con::warnf(ConsoleLogEntry::General, " Missing OpenAL function '%s', using emulated function", name); else Con::errorf(ConsoleLogEntry::General, " Missing OpenAL function '%s'", name); return (fnAddress != NULL); } /*! Get a function address for an OpenAL extension function and bind it * to it's function pointer */ static bool bindExtensionFunction( void *&fnAddress, const char *name ) { fnAddress = alGetProcAddress( (ALubyte*)name ); if( !fnAddress ) Con::errorf(ConsoleLogEntry::General, " Missing OpenAL Extension function '%s'", name); return (fnAddress != NULL); } /*! Bind the functions in the OpenAL DLL to the al interface functions */ static bool bindOpenALFunctions() { bool result = true; #define AL_FUNCTION(fn_return, fn_name, fn_args, fn_value) result &= bindFunction( *(void**)&fn_name, #fn_name); #include #include #undef AL_FUNCTION return result; } /*! Bind the stub functions to the al interface functions */ static void unbindOpenALFunctions() { #define AL_FUNCTION(fn_return, fn_name, fn_args, fn_value) fn_name = stub_##fn_name; #include #include #include #undef AL_FUNCTION } /*! Bind the EAX Extension functions to the EAX interface functions */ static bool bindEAXFunctions() { bool result = true; #define AL_FUNCTION(fn_return, fn_name, fn_args, fn_value) result &= bindExtensionFunction( *(void**)&fn_name, #fn_name); #include #undef AL_FUNCTION return result; } // Definitions for the emulated functions ALboolean emu_alGetBoolean(ALenum param) { ALboolean alboolean; alGetBooleanv(param, &alboolean); return alboolean; } ALint emu_alGetInteger(ALenum param) { ALint alint; alGetIntegerv(param, &alint); return alint; } ALfloat emu_alGetFloat(ALenum param) { ALfloat alfloat; alGetFloatv(param, &alfloat); return alfloat; } ALdouble emu_alGetDouble(ALenum param) { ALdouble aldouble; alGetDoublev(param, &aldouble); return aldouble; } void emu_alGetListener3f(ALenum pname,ALfloat *v0,ALfloat *v1,ALfloat *v2) { ALfloat ptArray[10]; ptArray[0] = *v0; ptArray[1] = *v1; ptArray[2] = *v2; alGetListenerfv(pname, ptArray); *v0 = ptArray[0]; *v1 = ptArray[1]; *v2 = ptArray[2]; } void emu_alListeneri( ALenum param, ALint value ) { alListenerf(param, static_cast(value)); } ALCdevice* emu_alcGetContextsDevice(ALCcontext *context) { // this function isn't emulated AssertFatal(false, "alcGetContextsDevice is not available"); return NULL; } namespace Audio { /*! Shutdown and Unload the OpenAL DLL */ void OpenALDLLShutdown() { if (dlHandle != NULL) { dlclose(dlHandle); // FreeBSD didn't like that const dlerror() was returning. if ((dlError = (char *)dlerror()) != NULL) Con::errorf(ConsoleLogEntry::General, " Error unloading OpenAL Library: %s", dlError); } dlHandle = NULL; unbindOpenALFunctions(); } /*! Dynamically Loads the OpenAL DLL if present and binds all the functions. * If there is no DLL or an unexpected error occurs binding functions the * stub functions are automatically bound. */ bool OpenALDLLInit() { OpenALDLLShutdown(); const char* libName = "libopenal.so"; // these are relative to the current working directory const char* searchPath[] = { "lib", "tplib", // superceeded by "lib", here for backass compatibility "", // i.e.: current working directory NULL // this must be last }; char openalPath[4096]; for (int i = 0; searchPath[i] != NULL; ++i) { dSprintf(openalPath, sizeof(openalPath), "%s/%s/%s", Platform::getWorkingDirectory(), searchPath[i], libName); Con::printf(" Searching for OpenAl at location : %s", openalPath); dlHandle = dlopen(openalPath, RTLD_NOW); if (dlHandle != NULL) { // found it Con::printf(" Loading OpenAL: %s", openalPath); break; } } if (dlHandle == NULL) { // couldn't find it in our searchPath, try the system path dlHandle = dlopen(libName, RTLD_NOW); if (dlHandle != NULL) Con::printf(" Loading OpenAL from system (dlopen) path"); } if (dlHandle != NULL) { // if the DLL loaded bind the OpenAL function pointers if(bindOpenALFunctions()) { // if EAX is available bind it's function pointers if (alIsExtensionPresent((ALubyte*)"EAX" )) bindEAXFunctions(); return(true); } // an error occured, shutdown OpenALDLLShutdown(); } else { Con::errorf(ConsoleLogEntry::General, " Error loading OpenAL Library: %s", dlerror()); } return(false); } } // end namespace Audio