fixed address checking issue

fixed issue with ALC error checking not taking a device into account
now tracking device and context create and destroy
made the create with open default device option public
misc cleaning up and commenting
This commit is contained in:
Brian Matzon 2007-05-19 19:37:57 +00:00
parent e4745f5728
commit d0956ea179
6 changed files with 200 additions and 66 deletions

View File

@ -31,15 +31,15 @@
*/
package org.lwjgl.openal;
import java.util.Vector;
import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil;
import org.lwjgl.Sys;
/**
* <br>
* This is the OpenAL class. It extends the latest core.
* <p>
* The AL class implements the actual creation code for linking to the native library
* OpenAL.
* </p>
*
* @author Brian Matzon <brian@matzon.dk>
* @version $Revision$
@ -108,7 +108,7 @@ public final class AL {
* @param openDevice Whether to automatically open the device
* @see #create(String, int, int, boolean)
*/
static void create(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized, boolean openDevice)
public static void create(String deviceArguments, int contextFrequency, int contextRefresh, boolean contextSynchronized, boolean openDevice)
throws LWJGLException {
if (created)
@ -196,6 +196,7 @@ public final class AL {
*/
public static void destroy() {
if (context != null) {
ALC10.alcMakeContextCurrent(null);
ALC10.alcDestroyContext(context);
context = null;
}

View File

@ -33,16 +33,12 @@ package org.lwjgl.openal;
import java.nio.Buffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import org.lwjgl.BufferChecks;
import org.lwjgl.LWJGLException;
/**
*
* <p>
* This is the context class for OpenAL. This class implements functions
* in alc.h
* </p>
*
* <p>
* ALC introduces the notion of a Device. A Device can be, depending on the
@ -54,19 +50,18 @@ import org.lwjgl.LWJGLException;
* specifiers (represented as strings).
* </p>
*
* <p>
* <b>NOTE:</b><br>
* The LWJGL implementation of OpenAL does not expose the device, nor the context.
* Whenever <code>AL</code> is created using the <code>create</code> method, an underlying
* device and context is created. Thus more advanced usage of multiple contexts and/or devices
* are not possible. The above mentioned features are very rarely used in games.
* </p>
*
* @author Brian Matzon <brian@matzon.dk>
* @version $Revision: 2286 $
* $Id: ALC.java 2286 2006-03-23 19:32:21 +0000 (to, 23 mar 2006) matzon $
*/
public final class ALC10 {
/** List of active contexts */
static HashMap contexts = new HashMap();
/** List of active devices */
static HashMap devices = new HashMap();
/** Bad value */
public static final int ALC_INVALID = 0;
@ -158,10 +153,10 @@ public final class ALC10 {
public static String alcGetString(ALCdevice device, int pname) {
String result;
result = nalcGetString(getDevice(device), pname);
Util.checkALCError();
Util.checkALCError(device);
return result;
}
private native static String nalcGetString(long device, int pname);
native static String nalcGetString(long device, int pname);
/**
* The application can query ALC for information using an integer query function.
@ -186,9 +181,9 @@ public final class ALC10 {
public static void alcGetInteger(ALCdevice device, int pname, IntBuffer integerdata) {
BufferChecks.checkDirect(integerdata);
nalcGetIntegerv(getDevice(device), pname, integerdata.remaining(), integerdata, integerdata.position());
Util.checkALCError();
Util.checkALCError(device);
}
private native static void nalcGetIntegerv(long device, int pname, int size, Buffer integerdata, int offset);
native static void nalcGetIntegerv(long device, int pname, int size, Buffer integerdata, int offset);
/**
* The <code>alcOpenDevice</code> function allows the application (i.e. the client program) to
@ -203,9 +198,13 @@ public final class ALC10 {
* @return opened device, or null
*/
public static ALCdevice alcOpenDevice(String devicename) {
long device = nalcOpenDevice(devicename);
if(device > 0) {
return new ALCdevice(device);
long device_address = nalcOpenDevice(devicename);
if(device_address != 0) {
ALCdevice device = new ALCdevice(device_address);
synchronized (ALC10.devices) {
devices.put(new Long(device_address), device);
}
return device;
}
return null;
}
@ -221,7 +220,13 @@ public final class ALC10 {
* @param device address of native device to close
*/
public static boolean alcCloseDevice(ALCdevice device) {
return nalcCloseDevice(getDevice(device));
boolean result = nalcCloseDevice(getDevice(device));
device.setInvalid();
synchronized (devices) {
devices.remove(new Long(device.device));
}
return result;
}
native static boolean nalcCloseDevice(long device);
@ -241,16 +246,20 @@ public final class ALC10 {
* @return New context, or null if creation failed
*/
public static ALCcontext alcCreateContext(ALCdevice device, IntBuffer attrList) {
long context = nalcCreateContext(getDevice(device), attrList);
Util.checkALCError();
long context_address = nalcCreateContext(getDevice(device), attrList);
Util.checkALCError(device);
if(context > 0) {
return new ALCcontext(context);
if(context_address != 0) {
ALCcontext context = new ALCcontext(context_address);
synchronized (ALC10.contexts) {
contexts.put(new Long(context_address), context);
}
device.addContext(context);
return context;
}
return null;
}
private native static long nalcCreateContext(long device, IntBuffer attrList);
native static long nalcCreateContext(long device, IntBuffer attrList);
/**
* To make a Context current with respect to AL Operation (state changes by issueing
@ -269,7 +278,7 @@ public final class ALC10 {
public static int alcMakeContextCurrent(ALCcontext context) {
return nalcMakeContextCurrent(getContext(context));
}
public native static int nalcMakeContextCurrent(long context);
native static int nalcMakeContextCurrent(long context);
/**
* The current context is the only context accessible to state changes by AL commands
@ -285,7 +294,7 @@ public final class ALC10 {
public static void alcProcessContext(ALCcontext context) {
nalcProcessContext(getContext(context));
}
private native static void nalcProcessContext(long context);
native static void nalcProcessContext(long context);
/**
* The application can query for, and obtain an handle to, the current context for the
@ -294,13 +303,16 @@ public final class ALC10 {
* @return Current ALCcontext
*/
public static ALCcontext alcGetCurrentContext() {
long context = nalcGetCurrentContext();
if(context > 0) {
return new ALCcontext(context);
ALCcontext context = null;
long context_address = nalcGetCurrentContext();
if(context_address != 0) {
synchronized (ALC10.contexts) {
context = (ALCcontext) ALC10.contexts.get(new Long(context_address));
}
}
return null;
return context;
}
public native static long nalcGetCurrentContext();
native static long nalcGetCurrentContext();
/**
* The application can query for, and obtain an handle to, the device of a given context.
@ -309,13 +321,16 @@ public final class ALC10 {
* @param ALCdevice associated with context
*/
public static ALCdevice alcGetContextsDevice(ALCcontext context) {
long device = nalcGetContextsDevice(getContext(context));
if (device > 0) {
return new ALCdevice(device);
ALCdevice device = null;
long device_address = nalcGetContextsDevice(getContext(context));
if (device_address != 0) {
synchronized (ALC10.devices) {
device = (ALCdevice) ALC10.devices.get(new Long(device_address));
}
}
return null;
return device;
}
private native static long nalcGetContextsDevice(long context);
native static long nalcGetContextsDevice(long context);
/**
* The application can suspend any context from processing (including the current
@ -332,7 +347,7 @@ public final class ALC10 {
public static void alcSuspendContext(ALCcontext context) {
nalcSuspendContext(getContext(context));
}
private native static void nalcSuspendContext(long context);
native static void nalcSuspendContext(long context);
/**
* The correct way to destroy a context is to first release it using <code>alcMakeCurrent</code> and
@ -342,6 +357,7 @@ public final class ALC10 {
*/
public static void alcDestroyContext(ALCcontext context) {
nalcDestroyContext(getContext(context));
context.setInvalid();
}
native static void nalcDestroyContext(long context);
@ -363,7 +379,7 @@ public final class ALC10 {
public static int alcGetError(ALCdevice device) {
return nalcGetError(getDevice(device));
}
private native static int nalcGetError(long device);
native static int nalcGetError(long device);
/**
* Verify that a given extension is available for the current context and the device it
@ -376,10 +392,10 @@ public final class ALC10 {
*/
public static boolean alcIsExtensionPresent(ALCdevice device, String extName) {
boolean result = nalcIsExtensionPresent(getDevice(device), extName);
Util.checkALCError();
Util.checkALCError(device);
return result;
}
private native static boolean nalcIsExtensionPresent(long device, String extName);
native static boolean nalcIsExtensionPresent(long device, String extName);
/**
* Enumeration/token values are device independend, but tokens defined for
@ -393,13 +409,14 @@ public final class ALC10 {
*/
public static int alcGetEnumValue(ALCdevice device, String enumName) {
int result = nalcGetEnumValue(getDevice(device), enumName);
Util.checkALCError();
Util.checkALCError(device);
return result;
}
private native static int nalcGetEnumValue(long device, String enumName);
native static int nalcGetEnumValue(long device, String enumName);
static long getDevice(ALCdevice device) {
if(device != null) {
Util.checkALCValidDevice(device);
return device.device;
}
return 0L;
@ -407,6 +424,7 @@ public final class ALC10 {
static long getContext(ALCcontext context) {
if(context != null) {
Util.checkALCValidContext(context);
return context.context;
}
return 0L;

View File

@ -40,8 +40,13 @@ import org.lwjgl.LWJGLUtil;
/**
* <p>
* The ALC11 class implements features in OpenAL 1.1, specifically
* ALC methods and properties.
* </p>
*
* @author Brian Matzon <brian@matzon.dk>
* @see ALC10
* @version $Revision: 2286 $
* $Id: ALC.java 2286 2006-03-23 19:32:21 +0000 (to, 23 mar 2006) matzon $
*/
@ -81,9 +86,13 @@ public final class ALC11 {
* @return ALCdevice if it was possible to open a device
*/
public static ALCdevice alcCaptureOpenDevice(String devicename, int frequency, int format, int buffersize) {
long device = nalcCaptureOpenDevice(devicename, frequency, format, buffersize);
if(device > 0) {
return new ALCdevice(device);
long device_address = nalcCaptureOpenDevice(devicename, frequency, format, buffersize);
if(device_address != 0) {
ALCdevice device = new ALCdevice(device_address);
synchronized (ALC10.devices) {
ALC10.devices.put(new Long(device_address), device);
}
return device;
}
return null;
}
@ -99,7 +108,12 @@ public final class ALC11 {
* @return true if device was successfully closed
*/
public static boolean alcCaptureCloseDevice(ALCdevice device) {
return nalcCaptureCloseDevice(ALC10.getDevice(device));
boolean result = nalcCaptureCloseDevice(ALC10.getDevice(device));
device.setInvalid();
synchronized (ALC10.devices) {
ALC10.devices.remove(new Long(device.device));
}
return result;
}
static native boolean nalcCaptureCloseDevice(long device);

View File

@ -36,8 +36,14 @@ import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
/**
* <br>
* Wrapper class, to make ALC contexts behave like the orginal api.
* The ALCcontext class represents a context opened in OpenAL space.
*
* All operations of the AL core API affect a current AL context. Within the scope of AL,
* the ALC is implied - it is not visible as a handle or function parameter. Only one AL
* Context per process can be current at a time. Applications maintaining multiple AL
* Contexts, whether threaded or not, have to set the current context accordingly.
* Applications can have multiple threads that share one more or contexts. In other words,
* AL and ALC are threadsafe.
*
* @author Brian Matzon <brian@matzon.dk>
* @version $Revision$
@ -45,9 +51,12 @@ import org.lwjgl.BufferUtils;
*/
public final class ALCcontext {
/** address of actual context */
/** Address of actual context */
final long context;
/** Whether this context is valid */
private boolean valid = false;
/**
* Creates a new instance of ALCcontext
*
@ -55,6 +64,7 @@ public final class ALCcontext {
*/
ALCcontext(long context) {
this.context = context;
this.valid = true;
}
/*
@ -62,7 +72,7 @@ public final class ALCcontext {
*/
public boolean equals(Object context) {
if(context instanceof ALCcontext) {
return ((ALCcontext)context).context == this.context;
return ((ALCcontext)context).context == this.context && ((ALCcontext)context).valid == this.valid;
}
return super.equals(context);
}
@ -87,4 +97,19 @@ public final class ALCcontext {
return attribList;
}
/**
* Marks this context as invalid
*
*/
void setInvalid() {
valid = false;
}
/**
* @return true if this context is still valid
*/
public boolean isValid() {
return valid;
}
}

View File

@ -31,9 +31,18 @@
*/
package org.lwjgl.openal;
import java.util.HashMap;
import java.util.Iterator;
/**
* <br>
* Wrapper class, to make ALC devices behave like the orginal api.
* The ALCdevice class represents a device opened in OpenAL space.
*
* ALC introduces the notion of a Device. A Device can be, depending on the
* implementation, a hardware device, or a daemon/OS service/actual server. This
* mechanism also permits different drivers (and hardware) to coexist within the same
* system, as well as allowing several applications to share system resources for audio,
* including a single hardware output device. The details are left to the implementation,
* which has to map the available backends to unique device specifiers.
*
* @author Brian Matzon <brian@matzon.dk>
* @version $Revision$
@ -41,9 +50,15 @@ package org.lwjgl.openal;
*/
public final class ALCdevice {
/** address of actual device */
/** Address of actual device */
final long device;
/** Whether this device is valid */
private boolean valid = false;
/** List of contexts belonging to the device */
private HashMap contexts = new HashMap();
/**
* Creates a new instance of ALCdevice
*
@ -51,6 +66,7 @@ public final class ALCdevice {
*/
ALCdevice(long device) {
this.device = device;
this.valid = true;
}
/*
@ -58,8 +74,40 @@ public final class ALCdevice {
*/
public boolean equals(Object device) {
if(device instanceof ALCdevice) {
return ((ALCdevice)device).device == this.device;
return ((ALCdevice)device).device == this.device && ((ALCdevice)device).valid == this.valid;
}
return super.equals(device);
}
/**
* Adds a context to the device
*
* @param context context to add to the list of contexts for this device
*/
void addContext(ALCcontext context) {
synchronized (contexts) {
contexts.put(new Long(context.context), context);
}
}
/**
* Marks this device and all of its contexts invalid
*/
void setInvalid() {
valid = false;
synchronized (contexts) {
for(Iterator i = contexts.values().iterator(); i.hasNext();) {
ALCcontext context = (ALCcontext) i.next();
context.setInvalid();
}
}
contexts.clear();
}
/**
* @return true if this device is still valid
*/
public boolean isValid() {
return valid;
}
}

View File

@ -33,9 +33,10 @@ package org.lwjgl.openal;
/**
* Simple utility class.
* Simple utility class for checking AL/ALC errors
*
* @author cix_foo <cix_foo@users.sourceforge.net>
* @author Brian Matzon <brian@matzon.dk>
* @version $Revision$
*/
@ -44,15 +45,42 @@ public final class Util {
private Util() {
}
public static void checkALCError() {
int err = ALC10.alcGetError(AL.getDevice());
/**
* Checks for any ALC errors and throws an unchecked exception on errors
* @param device Device for which to check ALC errors
*/
public static void checkALCError(ALCdevice device) {
int err = ALC10.alcGetError(device);
if (err != ALC10.ALC_NO_ERROR)
throw new OpenALException(ALC10.alcGetString(AL.getDevice(), err));
}
/**
* Checks for any AL errors and throws an unchecked exception on errors
*/
public static void checkALError() {
int err = AL10.alGetError();
if (err != AL10.AL_NO_ERROR)
throw new OpenALException(err);
}
/**
* Checks for a valid device
* @param device ALCdevice to check the validity of
*/
public static void checkALCValidDevice(ALCdevice device) {
if(!device.isValid()) {
throw new OpenALException("Invalid device: " + device);
}
}
/**
* Checks for a valid context
* @param context ALCcontext to check the validity of
*/
public static void checkALCValidContext(ALCcontext context) {
if(!context.isValid()) {
throw new OpenALException("Invalid context: " + context);
}
}
}