diff --git a/src/java/org/lwjgl/openal/AL.java b/src/java/org/lwjgl/openal/AL.java index cd9c6949..5b20eb59 100644 --- a/src/java/org/lwjgl/openal/AL.java +++ b/src/java/org/lwjgl/openal/AL.java @@ -61,7 +61,7 @@ public abstract class AL { * String that requests a certain device or device configuration. * If null is specified, the implementation will provide an * implementation specific default. - */ + */ protected static String deviceArguments; /** Frequency for mixing output buffer, in units of Hz. */ @@ -73,40 +73,40 @@ public abstract class AL { /** Flag, indicating a synchronous context. */ protected static int contextSynchronized = ALC.ALC_FALSE; - /** Have we been created? */ - protected static boolean created; + /** Have we been created? */ + protected static boolean created; - static { - initialize(); - } + static { + initialize(); + } - /** - * Static initialization - */ - private static void initialize() { - System.loadLibrary(org.lwjgl.Sys.getLibraryName()); - } + /** + * Static initialization + */ + private static void initialize() { + System.loadLibrary(org.lwjgl.Sys.getLibraryName()); + } - /** - * Native method to create AL instance - * - * @param oalPaths Array of strings containing paths to search for OpenAL library - * @return true if the AL creation process succeeded - */ - protected static native void nCreate(String[] oalPaths) throws OpenALException; + /** + * Native method to create AL instance + * + * @param oalPaths Array of strings containing paths to search for OpenAL library + * @return true if the AL creation process succeeded + */ + protected static native void nCreate(String[] oalPaths) throws OpenALException; - /** - * Native method the destroy the AL - */ - protected static native void nDestroy(); - - /** - * @return true if AL has been created - */ - public static boolean isCreated() { - return created; - } - + /** + * Native method the destroy the AL + */ + protected static native void nDestroy(); + + /** + * @return true if AL has been created + */ + public static boolean isCreated() { + return created; + } + /** * Creates an OpenAL instance. Using this constructor will cause OpenAL to * open the device using supplied device argument, and create a context using the context values @@ -119,12 +119,12 @@ public abstract class AL { */ public static void create(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized) throws OpenALException { - - if (created) { - return; - } - - + + if (created) { + return; + } + + AL.deviceArguments = deviceArguments; AL.contextFrequency = contextFrequency; AL.contextRefresh = contextRefresh; @@ -138,55 +138,50 @@ public abstract class AL { * open the default device, and create a context using default values. */ public static void create() throws OpenALException { - if(created) { - return; - } + if(created) { + return; + } - // need to pass path of possible locations of OAL to native side - String libpath = System.getProperty("java.library.path"); - String seperator = System.getProperty("path.separator"); - String libname; - String jwsLibname; + // need to pass path of possible locations of OAL to native side + String libpath = System.getProperty("java.library.path"); + String seperator = System.getProperty("path.separator"); + String jwsLibname; - // libname is hardcoded atm - this will change in a near future... - switch (Display.getPlatform()) { - case Display.PLATFORM_WGL: - libname = "lwjglaudio.dll"; - jwsLibname = "lwjglaudio"; - break; - case Display.PLATFORM_GLX: - libname = "libopenal.so"; - jwsLibname = "openal"; - break; - case Display.PLATFORM_AGL: - libname = "openal.dylib"; - jwsLibname = "openal"; - break; - default: - throw new OpenALException("Unknown platform"); - } - - String jwsPath = getPathFromJWS(jwsLibname); - if (jwsPath != null) { - libpath += seperator - + jwsPath.substring(0, jwsPath.lastIndexOf(File.separator)); - } + switch (Display.getPlatform()) { + case Display.PLATFORM_WGL: + jwsLibname = "lwjglaudio"; + break; + case Display.PLATFORM_GLX: + jwsLibname = "openal"; + break; + case Display.PLATFORM_AGL: + jwsLibname = "openal"; + break; + default: + throw new OpenALException("Unknown platform"); + } + + String jwsPath = getPathFromJWS(jwsLibname); + if (jwsPath != null) { + libpath += seperator + + jwsPath.substring(0, jwsPath.lastIndexOf(File.separator)); + } - StringTokenizer st = new StringTokenizer(libpath, seperator); + StringTokenizer st = new StringTokenizer(libpath, seperator); - //create needed string array - String[] oalPaths = new String[st.countTokens() + 1]; + //create needed string array + String[] oalPaths = new String[st.countTokens() + 1]; - //build paths - for (int i = 0; i < oalPaths.length - 1; i++) { - oalPaths[i] = st.nextToken() + File.separator + libname; - } + //build paths + for (int i = 0; i < oalPaths.length - 1; i++) { + oalPaths[i] = st.nextToken() + File.separator; + } - //add cwd path - oalPaths[oalPaths.length - 1] = libname; - nCreate(oalPaths); + //add cwd path + oalPaths[oalPaths.length - 1] = ""; + nCreate(oalPaths); - ALC.create(); + ALC.create(); device = ALC.alcOpenDevice(deviceArguments); @@ -202,17 +197,17 @@ public abstract class AL { ALC.alcMakeContextCurrent(context.context); - created = true; + created = true; } /** * Exit cleanly by calling destroy. */ public static void destroy() { - if(!created) { - return; - } - + if(!created) { + return; + } + ALC.alcDestroyContext(context.context); ALC.alcCloseDevice(device.device); ALC.destroy(); @@ -225,36 +220,36 @@ public abstract class AL { contextFrequency = -1; contextRefresh = -1; contextSynchronized = ALC.ALC_FALSE; - - created = false; - nDestroy(); + + created = false; + nDestroy(); } - - /** - * Tries to locate OpenAL from the JWS Library path - * This method exists because OpenAL is loaded from native code, and as such - * is exempt from JWS library loading rutines. OpenAL therefore always fails. - * We therefore invoke the protected method of the JWS classloader to see if it can - * locate it. - * - * @param libname Name of library to search for - * @return Absolute path to library if found, otherwise null - */ - private static String getPathFromJWS(String libname) { - try { + + /** + * Tries to locate OpenAL from the JWS Library path + * This method exists because OpenAL is loaded from native code, and as such + * is exempt from JWS library loading rutines. OpenAL therefore always fails. + * We therefore invoke the protected method of the JWS classloader to see if it can + * locate it. + * + * @param libname Name of library to search for + * @return Absolute path to library if found, otherwise null + */ + private static String getPathFromJWS(String libname) { + try { - Sys.log("JWS Classloader looking for: " + libname); - - Object o = AL.class.getClassLoader(); - Class c = o.getClass(); - Method findLibrary = - c.getMethod("findLibrary", new Class[] { String.class }); - Object[] arguments = new Object[] { libname }; - return (String) findLibrary.invoke(o, arguments); + Sys.log("JWS Classloader looking for: " + libname); + + Object o = AL.class.getClassLoader(); + Class c = o.getClass(); + Method findLibrary = + c.getMethod("findLibrary", new Class[] { String.class }); + Object[] arguments = new Object[] { libname }; + return (String) findLibrary.invoke(o, arguments); - } catch (Exception e) { - Sys.log("Failure locating OpenAL using classloader:" + e); - } - return null; - } -} \ No newline at end of file + } catch (Exception e) { + Sys.log("Failure locating OpenAL using classloader:" + e); + } + return null; + } +} diff --git a/src/native/common/extal.cpp b/src/native/common/extal.cpp index 51bdf362..e894d8a7 100644 --- a/src/native/common/extal.cpp +++ b/src/native/common/extal.cpp @@ -31,6 +31,8 @@ */ #include +#include +#include #include "extal.h" #include "common_tools.h" @@ -125,6 +127,9 @@ EAXGet eaxGet; // EAXGet function, ret$ HMODULE handleOAL; #endif #ifdef _X11 +void* handleOGG; +void* handleVorbis; +void* handleVorbisFile; void* handleOAL; #endif #ifdef _AGL @@ -187,6 +192,35 @@ static void* GetFunctionPointer(const char* function) { return p; } +/** + * Concatenate two strings + */ +static char *concatenate(const char *str1, const char *str2) { + int length1 = strlen(str1); + int length2 = strlen(str2); + char *str = (char *)calloc(length1 + length2 + 1, sizeof(char)); + strncpy(str, str1, length1); + strncpy(str + length1, str2, length2 + 1); + return str; +} + +#ifdef _X11 +static void closeVorbisLibs(void) { + if (handleOGG != NULL) { + dlclose(handleOGG); + handleOGG = NULL; + } + if (handleVorbis != NULL) { + dlclose(handleVorbis); + handleVorbis = NULL; + } + if (handleVorbisFile != NULL) { + dlclose(handleVorbisFile); + handleVorbisFile = NULL; + } +} +#endif + /** * Loads the OpenAL Library */ @@ -199,13 +233,35 @@ static bool LoadOpenAL(JNIEnv *env, jobjectArray oalPaths) { const char *path_str = env->GetStringUTFChars(path, NULL); printfDebug("Testing '%s'\n", path_str); #ifdef _WIN32 - handleOAL = LoadLibrary(path_str); + char *lib_str = concatenate(path_str, "lwjglaudio.dll"); + handleOAL = LoadLibrary(lib_str); + free(lib_str); #endif #ifdef _X11 - handleOAL = dlopen(path_str, RTLD_LAZY); + char *lib_str = concatenate(path_str, "libogg.so.0"); + handleOGG = dlopen(lib_str, RTLD_LAZY); + free(lib_str); + + lib_str = concatenate(path_str, "libvorbis.so.0"); + handleVorbis = dlopen(lib_str, RTLD_LAZY); + free(lib_str); + + lib_str = concatenate(path_str, "libvorbisfile.so.3"); + handleVorbisFile = dlopen(lib_str, RTLD_LAZY); + free(lib_str); + + lib_str = concatenate(path_str, "libopenal.so"); + handleOAL = dlopen(lib_str, RTLD_LAZY); + free(lib_str); + + if (handleOAL == NULL) { + closeVorbisLibs(); + } #endif #ifdef _AGL - handleOAL = NSAddImage(path_str, NSADDIMAGE_OPTION_RETURN_ON_ERROR); + char *lib_str = concatenate(path_str, "openal.dylib"); + handleOAL = NSAddImage(lib_str, NSADDIMAGE_OPTION_RETURN_ON_ERROR); + free(lib_str); #endif if (handleOAL != NULL) { printfDebug("Found OpenAL at '%s'\n", path_str); @@ -225,7 +281,11 @@ static void UnLoadOpenAL() { FreeLibrary(handleOAL); #endif #ifdef _X11 - dlclose(handleOAL); + if (handleOAL != NULL) { + dlclose(handleOAL); + handleOAL = NULL; + } + closeVorbisLibs(); #endif #ifdef _AGL // Cannot remove the image