/* * Copyright (c) 2002-2008 LWJGL Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'LWJGL' nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.lwjgl.openal; import org.lwjgl.LWJGLException; import org.lwjgl.LWJGLUtil; import org.lwjgl.Sys; import java.util.Arrays; /** *

* The AL class implements the actual creation code for linking to the native library * OpenAL. *

* * @author Brian Matzon * @version $Revision$ * $Id$ */ public final class AL { /** ALCdevice instance. */ static ALCdevice device; /** Current ALCcontext. */ static ALCcontext context; /** Have we been created? */ private static boolean created; static { Sys.initialize(); } private AL() { } /** * Native method to create AL instance * * @param oalPath Path to search for OpenAL library */ private static native void nCreate(String oalPath) throws LWJGLException; /** * Native method to create AL instance from the Mac OS X 10.4 OpenAL framework. * It is only defined in the Mac OS X native library. */ private static native void nCreateDefault() throws LWJGLException; /** * Native method the destroy the AL */ private 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 * supplied. * * @param deviceArguments Arguments supplied to native device * @param contextFrequency Frequency for mixing output buffer, in units of Hz (Common values include 11025, 22050, and 44100). * @param contextRefresh Refresh intervalls, in units of Hz. * @param contextSynchronized Flag, indicating a synchronous context.* */ public static void create(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized) throws LWJGLException { create(deviceArguments, contextFrequency, contextRefresh, contextSynchronized, true); } /** * @param openDevice Whether to automatically open the device * @see #create(String, int, int, boolean) */ public static void create(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized, boolean openDevice) throws LWJGLException { if (created) throw new IllegalStateException("Only one OpenAL context may be instantiated at any one time."); String libname; String[] library_names; switch (LWJGLUtil.getPlatform()) { case LWJGLUtil.PLATFORM_WINDOWS: if ( Sys.is64Bit() ) { libname = "OpenAL64"; library_names = new String[]{"OpenAL64.dll"}; } else { libname = "OpenAL32"; library_names = new String[]{"OpenAL32.dll"}; } break; case LWJGLUtil.PLATFORM_LINUX: libname = "openal"; library_names = new String[]{"libopenal64.so", "libopenal.so", "libopenal.so.0"}; break; case LWJGLUtil.PLATFORM_MACOSX: libname = "openal"; library_names = new String[]{"openal.dylib"}; break; default: throw new LWJGLException("Unknown platform: " + LWJGLUtil.getPlatform()); } String[] oalPaths = LWJGLUtil.getLibraryPaths(libname, library_names, AL.class.getClassLoader()); LWJGLUtil.logger().log(() -> "Found " + oalPaths.length + " OpenAL paths: " + Arrays.toString(oalPaths)); for ( String oalPath : oalPaths ) { try { nCreate(oalPath); created = true; init(deviceArguments, contextFrequency, contextRefresh, contextSynchronized, openDevice); break; } catch (LWJGLException e) { LWJGLUtil.log("Failed to load " + oalPath + ": " + e.getMessage()); } } if (!created && LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_MACOSX) { // Try to load OpenAL from the framework instead nCreateDefault(); created = true; init(deviceArguments, contextFrequency, contextRefresh, contextSynchronized, openDevice); } if (!created) throw new LWJGLException("Could not locate OpenAL library."); } private static void init(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized, boolean openDevice) throws LWJGLException { try { AL10.initNativeStubs(); ALC10.initNativeStubs(); if(openDevice) { device = ALC10.alcOpenDevice(deviceArguments); if (device == null) { throw new LWJGLException("Could not open ALC device"); } if (contextFrequency == -1) { context = ALC10.alcCreateContext(device, null); } else { context = ALC10.alcCreateContext(device, ALCcontext.createAttributeList(contextFrequency, contextRefresh, contextSynchronized ? ALC10.ALC_TRUE : ALC10.ALC_FALSE)); } ALC10.alcMakeContextCurrent(context); } } catch (LWJGLException e) { destroy(); throw e; } ALC11.initialize(); // Load EFX10 native stubs if ALC_EXT_EFX is supported. // Is there any situation where the current device supports ALC_EXT_EFX and one // later created by the user does not? // Do we have to call resetNativeStubs(EFX10.class); somewhere? Not done for AL11 // either. // This can either be here or in ALC11, since ALC_EXT_EFX indirectly requires AL 1.1 // for functions like alSource3i. if (ALC10.alcIsExtensionPresent(device, EFX10.ALC_EXT_EFX_NAME)){ EFX10.initNativeStubs(); } } /** * Creates an OpenAL instance. The empty create will cause OpenAL to * open the default device, and create a context using default values. * This method used to use default values that the OpenAL implementation * chose but this produces unexpected results on some systems; so now * it defaults to 44100Hz mixing @ 60Hz refresh. */ public static void create() throws LWJGLException { create(null, 44100, 60, false); } /** * Exit cleanly by calling destroy. */ public static void destroy() { if (context != null) { ALC10.alcMakeContextCurrent(null); ALC10.alcDestroyContext(context); context = null; } if (device != null) { boolean result = ALC10.alcCloseDevice(device); device = null; } resetNativeStubs(AL10.class); resetNativeStubs(AL11.class); resetNativeStubs(ALC10.class); resetNativeStubs(ALC11.class); resetNativeStubs(EFX10.class); if (created) nDestroy(); created = false; } private static native void resetNativeStubs(Class clazz); /** * @return handle to the default AL context. */ public static ALCcontext getContext() { return context; } /** * @return handle to the default AL device. */ public static ALCdevice getDevice() { return device; } }