x86UNIXOpenAL.client.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platformX86UNIX/platformX86UNIX.h"
  23. #include "console/console.h"
  24. #include <dlfcn.h>
  25. #include <al/altypes.h>
  26. #include <al/alctypes.h>
  27. #define INITGUID
  28. #include <al/eaxtypes.h>
  29. // Define the OpenAL and Extension Stub functions
  30. #define AL_FUNCTION(fn_return, fn_name, fn_args, fn_value) fn_return stub_##fn_name fn_args{ fn_value }
  31. #include <al/al_func.h>
  32. #include <al/alc_func.h>
  33. #include <al/eax_func.h>
  34. #undef AL_FUNCTION
  35. // Declare the OpenAL and Extension Function pointers
  36. // And initialize them to the stub functions
  37. #define AL_FUNCTION(fn_return,fn_name,fn_args, fn_value) fn_return (*fn_name)fn_args = stub_##fn_name;
  38. #include <al/al_func.h>
  39. #include <al/alc_func.h>
  40. #include <al/eax_func.h>
  41. #undef AL_FUNCTION
  42. // Declarations for the "emulated" functions (al functions that don't
  43. // exist in the loki openal implementation)
  44. ALboolean emu_alGetBoolean(ALenum param);
  45. ALint emu_alGetInteger(ALenum param);
  46. ALfloat emu_alGetFloat(ALenum param);
  47. ALdouble emu_alGetDouble(ALenum param);
  48. void emu_alListeneri( ALenum param, ALint value );
  49. void emu_alGetListener3f(ALenum pname,ALfloat *v1,ALfloat *v2,ALfloat *v3);
  50. ALCdevice* emu_alcGetContextsDevice(ALCcontext *context);
  51. static void *dlHandle = NULL;
  52. static char* dlError = "no error";
  53. /*! Get an "emulated" function address and bind it to the function pointer
  54. */
  55. static bool bindEmulatedFunction(void *&fnAddress, const char *name)
  56. {
  57. fnAddress = NULL;
  58. if (dStrcmp(name, "alGetBoolean")==0)
  59. fnAddress = (void*)&emu_alGetBoolean;
  60. else if (dStrcmp(name, "alGetInteger")==0)
  61. fnAddress = (void*)&emu_alGetInteger;
  62. else if (dStrcmp(name, "alGetFloat")==0)
  63. fnAddress = (void*)&emu_alGetFloat;
  64. else if (dStrcmp(name, "alGetDouble")==0)
  65. fnAddress = (void*)&emu_alGetDouble;
  66. else if (dStrcmp(name, "alListeneri")==0)
  67. fnAddress = (void*)&emu_alListeneri;
  68. else if (dStrcmp(name, "alGetListener3f")==0)
  69. fnAddress = (void*)&emu_alGetListener3f;
  70. else if (dStrcmp(name, "alcGetContextsDevice")==0)
  71. fnAddress = (void*)&emu_alcGetContextsDevice;
  72. return fnAddress != NULL;
  73. }
  74. /*! Get a function address from the OpenAL DLL and bind it to the
  75. * function pointer
  76. */
  77. static bool bindFunction( void *&fnAddress, const char *name )
  78. {
  79. fnAddress = dlsym(dlHandle, name);
  80. if( !fnAddress )
  81. if (bindEmulatedFunction(fnAddress, name))
  82. Con::warnf(ConsoleLogEntry::General, " Missing OpenAL function '%s', using emulated function", name);
  83. else
  84. Con::errorf(ConsoleLogEntry::General, " Missing OpenAL function '%s'", name);
  85. return (fnAddress != NULL);
  86. }
  87. /*! Get a function address for an OpenAL extension function and bind it
  88. * to it's function pointer
  89. */
  90. static bool bindExtensionFunction( void *&fnAddress, const char *name )
  91. {
  92. fnAddress = alGetProcAddress( (ALubyte*)name );
  93. if( !fnAddress )
  94. Con::errorf(ConsoleLogEntry::General, " Missing OpenAL Extension function '%s'", name);
  95. return (fnAddress != NULL);
  96. }
  97. /*! Bind the functions in the OpenAL DLL to the al interface functions
  98. */
  99. static bool bindOpenALFunctions()
  100. {
  101. bool result = true;
  102. #define AL_FUNCTION(fn_return, fn_name, fn_args, fn_value) result &= bindFunction( *(void**)&fn_name, #fn_name);
  103. #include <al/al_func.h>
  104. #include <al/alc_func.h>
  105. #undef AL_FUNCTION
  106. return result;
  107. }
  108. /*! Bind the stub functions to the al interface functions
  109. */
  110. static void unbindOpenALFunctions()
  111. {
  112. #define AL_FUNCTION(fn_return, fn_name, fn_args, fn_value) fn_name = stub_##fn_name;
  113. #include <al/al_func.h>
  114. #include <al/alc_func.h>
  115. #include <al/eax_func.h>
  116. #undef AL_FUNCTION
  117. }
  118. /*! Bind the EAX Extension functions to the EAX interface functions
  119. */
  120. static bool bindEAXFunctions()
  121. {
  122. bool result = true;
  123. #define AL_FUNCTION(fn_return, fn_name, fn_args, fn_value) result &= bindExtensionFunction( *(void**)&fn_name, #fn_name);
  124. #include <al/eax_func.h>
  125. #undef AL_FUNCTION
  126. return result;
  127. }
  128. // Definitions for the emulated functions
  129. ALboolean emu_alGetBoolean(ALenum param)
  130. {
  131. ALboolean alboolean;
  132. alGetBooleanv(param, &alboolean);
  133. return alboolean;
  134. }
  135. ALint emu_alGetInteger(ALenum param)
  136. {
  137. ALint alint;
  138. alGetIntegerv(param, &alint);
  139. return alint;
  140. }
  141. ALfloat emu_alGetFloat(ALenum param)
  142. {
  143. ALfloat alfloat;
  144. alGetFloatv(param, &alfloat);
  145. return alfloat;
  146. }
  147. ALdouble emu_alGetDouble(ALenum param)
  148. {
  149. ALdouble aldouble;
  150. alGetDoublev(param, &aldouble);
  151. return aldouble;
  152. }
  153. void emu_alGetListener3f(ALenum pname,ALfloat *v0,ALfloat *v1,ALfloat *v2)
  154. {
  155. ALfloat ptArray[10];
  156. ptArray[0] = *v0;
  157. ptArray[1] = *v1;
  158. ptArray[2] = *v2;
  159. alGetListenerfv(pname, ptArray);
  160. *v0 = ptArray[0];
  161. *v1 = ptArray[1];
  162. *v2 = ptArray[2];
  163. }
  164. void emu_alListeneri( ALenum param, ALint value )
  165. {
  166. alListenerf(param, static_cast<ALfloat>(value));
  167. }
  168. ALCdevice* emu_alcGetContextsDevice(ALCcontext *context)
  169. {
  170. // this function isn't emulated
  171. AssertFatal(false, "alcGetContextsDevice is not available");
  172. return NULL;
  173. }
  174. namespace Audio
  175. {
  176. /*! Shutdown and Unload the OpenAL DLL
  177. */
  178. void OpenALDLLShutdown()
  179. {
  180. if (dlHandle != NULL)
  181. {
  182. dlclose(dlHandle);
  183. // FreeBSD didn't like that const dlerror() was returning.
  184. if ((dlError = (char *)dlerror()) != NULL)
  185. Con::errorf(ConsoleLogEntry::General, " Error unloading OpenAL Library: %s", dlError);
  186. }
  187. dlHandle = NULL;
  188. unbindOpenALFunctions();
  189. }
  190. /*! Dynamically Loads the OpenAL DLL if present and binds all the functions.
  191. * If there is no DLL or an unexpected error occurs binding functions the
  192. * stub functions are automatically bound.
  193. */
  194. bool OpenALDLLInit()
  195. {
  196. OpenALDLLShutdown();
  197. const char* libName = "libopenal.so";
  198. // these are relative to the current working directory
  199. const char* searchPath[] = {
  200. "lib",
  201. "tplib", // superceeded by "lib", here for backass compatibility
  202. "", // i.e.: current working directory
  203. NULL // this must be last
  204. };
  205. char openalPath[4096];
  206. for (int i = 0; searchPath[i] != NULL; ++i)
  207. {
  208. dSprintf(openalPath, sizeof(openalPath), "%s/%s/%s",
  209. Platform::getWorkingDirectory(),
  210. searchPath[i],
  211. libName);
  212. Con::printf(" Searching for OpenAl at location : %s", openalPath);
  213. dlHandle = dlopen(openalPath, RTLD_NOW);
  214. if (dlHandle != NULL)
  215. {
  216. // found it
  217. Con::printf(" Loading OpenAL: %s", openalPath);
  218. break;
  219. }
  220. }
  221. if (dlHandle == NULL)
  222. {
  223. // couldn't find it in our searchPath, try the system path
  224. dlHandle = dlopen(libName, RTLD_NOW);
  225. if (dlHandle != NULL)
  226. Con::printf(" Loading OpenAL from system (dlopen) path");
  227. }
  228. if (dlHandle != NULL)
  229. {
  230. // if the DLL loaded bind the OpenAL function pointers
  231. if(bindOpenALFunctions())
  232. {
  233. // if EAX is available bind it's function pointers
  234. if (alIsExtensionPresent((ALubyte*)"EAX" ))
  235. bindEAXFunctions();
  236. return(true);
  237. }
  238. // an error occured, shutdown
  239. OpenALDLLShutdown();
  240. }
  241. else
  242. {
  243. Con::errorf(ConsoleLogEntry::General, " Error loading OpenAL Library: %s", dlerror());
  244. }
  245. return(false);
  246. }
  247. } // end namespace Audio