/* * 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 java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.HashMap; import org.lwjgl.BufferChecks; import org.lwjgl.LWJGLException; import org.lwjgl.MemoryUtil; /** * *
* 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 (represented as strings). *
* * @author Brian MatzonALC_DEFAULT_DEVICE_SPECIFIER
- The specifer string for the default device
* ALC_DEVICE_SPECIFIER
- The specifer string for the device
* ALC_EXTENSIONS
- The extensions string for diagnostics and printing.
*
* In addition, printable error message strings are provided for all valid error tokens,
* including ALC_NO_ERROR
,ALC_INVALID_DEVICE
, ALC_INVALID_CONTEXT
,
* ALC_INVALID_ENUM
, ALC_INVALID_VALUE
.
*
* @param pname Property to get
* @return String property from device
*/
public static String alcGetString(ALCdevice device, int pname) {
ByteBuffer buffer = nalcGetString(getDevice(device), pname);
Util.checkALCError(device);
return MemoryUtil.decodeUTF8(buffer);
}
static native ByteBuffer nalcGetString(long device, int pname);
/**
* The application can query ALC for information using an integer query function.
* For some tokens, null
is a legal deviceHandle. In other cases, specifying a null
* device will generate an ALC_INVALID_DEVICE
error. The application has to
* specify the size of the destination buffer provided. A null
destination or a zero
* size parameter will cause ALC to ignore the query.
*
* ALC_MAJOR_VERSION
- Major version query.
* ALC_MINOR_VERSION
- Minor version query.
* ALC_ATTRIBUTES_SIZE
- The size required for the zero-terminated attributes list,
* for the current context. null
is an invalid device. null
(no current context
* for the specified device) is legal.
* ALC_ALL_ATTRIBUTES
- Expects a destination of ALC_CURRENT_ATTRIBUTES_SIZE
,
* and provides the attribute list for the current context of the specified device.
* null
is an invalid device. null
(no current context for the specified device)
* will return the default attributes defined by the specified device.
*
* @param pname Property to get
* @param integerdata ByteBuffer to write integers to
*/
public static void alcGetInteger(ALCdevice device, int pname, IntBuffer integerdata) {
BufferChecks.checkDirect(integerdata);
nalcGetIntegerv(getDevice(device), pname, integerdata.remaining(), MemoryUtil.getAddress(integerdata));
Util.checkALCError(device);
}
static native void nalcGetIntegerv(long device, int pname, int size, long integerdata);
/**
* The alcOpenDevice
function allows the application (i.e. the client program) to
* connect to a device (i.e. the server).
*
* If the function returns null
, then no sound driver/device has been found. The
* argument is a null terminated string that requests a certain device or device
* configuration. If null
is specified, the implementation will provide an
* implementation specific default.
*
* @param devicename name of device to open
* @return opened device, or null
*/
public static ALCdevice alcOpenDevice(String devicename) {
ByteBuffer buffer = MemoryUtil.encodeUTF8(devicename);
long device_address = nalcOpenDevice(MemoryUtil.getAddressSafe(buffer));
if(device_address != 0) {
ALCdevice device = new ALCdevice(device_address);
synchronized (ALC10.devices) {
devices.put(device_address, device);
}
return device;
}
return null;
}
static native long nalcOpenDevice(long devicename);
/**
* The alcCloseDevice
function allows the application (i.e. the client program) to
* disconnect from a device (i.e. the server).
*
* If deviceHandle is null
or invalid, an ALC_INVALID_DEVICE
error will be
* generated. Once closed, a deviceHandle is invalid.
*
* @param device address of native device to close
*/
public static boolean alcCloseDevice(ALCdevice device) {
boolean result = nalcCloseDevice(getDevice(device));
synchronized (devices) {
device.setInvalid();
devices.remove(Long.valueOf(device.device));
}
return result;
}
static native boolean nalcCloseDevice(long device);
/**
* A context is created using alcCreateContext
. The device parameter has to be a valid
* device. The attribute list can be null
, or a zero terminated list of integer pairs
* composed of valid ALC attribute tokens and requested values.
*
* Context creation will fail if the application requests attributes that, by themselves,
* can not be provided. Context creation will fail if the combination of specified
* attributes can not be provided. Context creation will fail if a specified attribute, or
* the combination of attributes, does not match the default values for unspecified
* attributes.
*
* @param device address of device to associate context to
* @param attrList Buffer to read attributes from
* @return New context, or null if creation failed
*/
public static ALCcontext alcCreateContext(ALCdevice device, IntBuffer attrList) {
long context_address = nalcCreateContext(getDevice(device), MemoryUtil.getAddressSafe(attrList));
Util.checkALCError(device);
if(context_address != 0) {
ALCcontext context = new ALCcontext(context_address);
synchronized (ALC10.contexts) {
contexts.put(context_address, context);
device.addContext(context);
}
return context;
}
return null;
}
static native long nalcCreateContext(long device, long attrList);
/**
* To make a Context current with respect to AL Operation (state changes by issueing
* commands), alcMakeContextCurrent
is used. The context parameter can be null
* or a valid context pointer. The operation will apply to the device that the context
* was created for.
*
* For each OS process (usually this means for each application), only one context can
* be current at any given time. All AL commands apply to the current context.
* Commands that affect objects shared among contexts (e.g. buffers) have side effects
* on other contexts.
*
* @param context address of context to make current
* @return true if successfull, false if not
*/
public static int alcMakeContextCurrent(ALCcontext context) {
return nalcMakeContextCurrent(getContext(context));
}
static native int nalcMakeContextCurrent(long context);
/**
* The current context is the only context accessible to state changes by AL commands
* (aside from state changes affecting shared objects). However, multiple contexts can
* be processed at the same time. To indicate that a context should be processed (i.e.
* that internal execution state like offset increments are supposed to be performed),
* the application has to use alcProcessContext
.
*
* Repeated calls to alcProcessContext
are legal, and do not affect a context that is
* already marked as processing. The default state of a context created by
* alcCreateContext is that it is not marked as processing.
*/
public static void alcProcessContext(ALCcontext context) {
nalcProcessContext(getContext(context));
}
static native void nalcProcessContext(long context);
/**
* The application can query for, and obtain an handle to, the current context for the
* application. If there is no current context, null
is returned.
*
* @return Current ALCcontext
*/
public static ALCcontext alcGetCurrentContext() {
ALCcontext context = null;
long context_address = nalcGetCurrentContext();
if(context_address != 0) {
synchronized (ALC10.contexts) {
context = ALC10.contexts.get(context_address);
}
}
return context;
}
static native long nalcGetCurrentContext();
/**
* The application can query for, and obtain an handle to, the device of a given context.
*
* @param context address of context to get device for
*/
public static ALCdevice alcGetContextsDevice(ALCcontext context) {
ALCdevice device = null;
long device_address = nalcGetContextsDevice(getContext(context));
if (device_address != 0) {
synchronized (ALC10.devices) {
device = ALC10.devices.get(device_address);
}
}
return device;
}
static native long nalcGetContextsDevice(long context);
/**
* The application can suspend any context from processing (including the current
* one). To indicate that a context should be suspended from processing (i.e. that
* internal execution state like offset increments is not supposed to be changed), the
* application has to use alcSuspendContext
.
*
* Repeated calls to alcSuspendContext
are legal, and do not affect a context that is
* already marked as suspended. The default state of a context created by
* alcCreateContext
is that it is marked as suspended.
*
* @param context address of context to suspend
*/
public static void alcSuspendContext(ALCcontext context) {
nalcSuspendContext(getContext(context));
}
static native void nalcSuspendContext(long context);
/**
* The correct way to destroy a context is to first release it using alcMakeCurrent
and
* null
. Applications should not attempt to destroy a current context.
*
* @param context address of context to Destroy
*/
public static void alcDestroyContext(ALCcontext context) {
synchronized(ALC10.contexts) {
ALCdevice device = alcGetContextsDevice(context);
nalcDestroyContext(getContext(context));
device.removeContext(context);
context.setInvalid();
}
}
static native void nalcDestroyContext(long context);
/**
* ALC uses the same conventions and mechanisms as AL for error handling. In
* particular, ALC does not use conventions derived from X11 (GLX) or Windows
* (WGL). The alcGetError
function can be used to query ALC errors.
*
* Error conditions are specific to the device.
*
* ALC_NO_ERROR - The device handle or specifier does name an accessible driver/server.
* ALC_INVALID_DEVICE
- The Context argument does not name a valid context.
* ALC_INVALID_CONTEXT
- The Context argument does not name a valid context.
* ALC_INVALID_ENUM
- A token used is not valid, or not applicable.
* ALC_INVALID_VALUE
- An value (e.g. attribute) is not valid, or not applicable.
*
* @return Errorcode from ALC statemachine
*/
public static int alcGetError(ALCdevice device) {
return nalcGetError(getDevice(device));
}
static native int nalcGetError(long device);
/**
* Verify that a given extension is available for the current context and the device it
* is associated with.
* A null
name argument returns ALC_FALSE
, as do invalid and unsupported string
* tokens.
*
* @param extName name of extension to find
* @return true if extension is available, false if not
*/
public static boolean alcIsExtensionPresent(ALCdevice device, String extName) {
ByteBuffer buffer = MemoryUtil.encodeASCII(extName);
boolean result = nalcIsExtensionPresent(getDevice(device), MemoryUtil.getAddress(buffer));
Util.checkALCError(device);
return result;
}
private static native boolean nalcIsExtensionPresent(long device, long extName);
/**
* Enumeration/token values are device independend, but tokens defined for
* extensions might not be present for a given device. But only the tokens defined
* by the AL core are guaranteed. Availability of extension tokens dependends on the ALC extension.
*
* Specifying a null
name parameter will cause an ALC_INVALID_VALUE
error.
*
* @param enumName name of enum to find
* @return value of enumeration
*/
public static int alcGetEnumValue(ALCdevice device, String enumName) {
ByteBuffer buffer = MemoryUtil.encodeASCII(enumName);
int result = nalcGetEnumValue(getDevice(device), MemoryUtil.getAddress(buffer));
Util.checkALCError(device);
return result;
}
private static native int nalcGetEnumValue(long device, long enumName);
static long getDevice(ALCdevice device) {
if(device != null) {
Util.checkALCValidDevice(device);
return device.device;
}
return 0L;
}
static long getContext(ALCcontext context) {
if(context != null) {
Util.checkALCValidContext(context);
return context.context;
}
return 0L;
}
}