1 /* 2 * Copyright (c) 2002-2008 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.lwjgl.openal; 33 34 import java.nio.ByteBuffer; 35 import java.nio.IntBuffer; 36 import java.util.HashMap; 37 38 import org.lwjgl.BufferChecks; 39 import org.lwjgl.LWJGLException; 40 import org.lwjgl.MemoryUtil; 41 42 /** 43 * 44 * <p> 45 * ALC introduces the notion of a Device. A Device can be, depending on the 46 * implementation, a hardware device, or a daemon/OS service/actual server. This 47 * mechanism also permits different drivers (and hardware) to coexist within the same 48 * system, as well as allowing several applications to share system resources for audio, 49 * including a single hardware output device. The details are left to the 50 * implementation, which has to map the available backends to unique device 51 * specifiers (represented as strings). 52 * </p> 53 * 54 * @author Brian Matzon <brian@matzon.dk> 55 * @version $Revision: 2286 $ 56 * $Id: ALC.java 2286 2006-03-23 19:32:21 +0000 (to, 23 mar 2006) matzon $ 57 */ 58 public final class ALC10 { 59 60 /** List of active contexts */ 61 static final HashMap<Long, ALCcontext> contexts = new HashMap<Long, ALCcontext>(); 62 63 /** List of active devices */ 64 static final HashMap<Long, ALCdevice> devices = new HashMap<Long, ALCdevice>(); 65 66 /** Bad value */ 67 public static final int ALC_INVALID = 0; 68 69 /** Boolean False */ 70 public static final int ALC_FALSE = 0; 71 72 /** Boolean True */ 73 public static final int ALC_TRUE = 1; 74 75 /** Errors: No Error */ 76 public static final int ALC_NO_ERROR = ALC_FALSE; 77 78 /** Major version query. */ 79 public static final int ALC_MAJOR_VERSION = 0x1000; 80 81 /** Minor version query. */ 82 public static final int ALC_MINOR_VERSION = 0x1001; 83 84 /** 85 * The size required for the zero-terminated attributes list, for the current context. 86 **/ 87 public static final int ALC_ATTRIBUTES_SIZE = 0x1002; 88 89 /** 90 * Expects a destination of ALC_CURRENT_ATTRIBUTES_SIZE, 91 * and provides the attribute list for the current context of the specified device. 92 */ 93 public static final int ALC_ALL_ATTRIBUTES = 0x1003; 94 95 /** The specifier string for the default device */ 96 public static final int ALC_DEFAULT_DEVICE_SPECIFIER = 0x1004; 97 98 /** The specifier string for the device */ 99 public static final int ALC_DEVICE_SPECIFIER = 0x1005; 100 101 /** The extensions string for diagnostics and printing */ 102 public static final int ALC_EXTENSIONS = 0x1006; 103 104 /** Frequency for mixing output buffer, in units of Hz. */ 105 public static final int ALC_FREQUENCY = 0x1007; 106 107 /** Refresh intervalls, in units of Hz. */ 108 public static final int ALC_REFRESH = 0x1008; 109 110 /** Flag, indicating a synchronous context. */ 111 public static final int ALC_SYNC = 0x1009; 112 113 /** The device argument does not name a valid device */ 114 public static final int ALC_INVALID_DEVICE = 0xA001; 115 116 /** The context argument does not name a valid context */ 117 public static final int ALC_INVALID_CONTEXT = 0xA002; 118 119 /** 120 * A function was called at inappropriate time, or in an inappropriate way, 121 * causing an illegal state. This can be an incompatible ALenum, object ID, 122 * and/or function. 123 */ 124 public static final int ALC_INVALID_ENUM = 0xA003; 125 126 /** 127 * Illegal value passed as an argument to an AL call. 128 * Applies to parameter values, but not to enumerations. 129 */ 130 public static final int ALC_INVALID_VALUE = 0xA004; 131 132 /** 133 * A function could not be completed, because there is not enough 134 * memory available. 135 */ 136 public static final int ALC_OUT_OF_MEMORY = 0xA005; 137 initNativeStubs()138 static native void initNativeStubs() throws LWJGLException; 139 140 /** 141 * The application can obtain certain strings from ALC. 142 * 143 * <code>ALC_DEFAULT_DEVICE_SPECIFIER</code> - The specifer string for the default device 144 * <code>ALC_DEVICE_SPECIFIER</code> - The specifer string for the device 145 * <code>ALC_EXTENSIONS</code> - The extensions string for diagnostics and printing. 146 * 147 * In addition, printable error message strings are provided for all valid error tokens, 148 * including <code>ALC_NO_ERROR</code>,<code>ALC_INVALID_DEVICE</code>, <code>ALC_INVALID_CONTEXT</code>, 149 * <code>ALC_INVALID_ENUM</code>, <code>ALC_INVALID_VALUE</code>. 150 * 151 * @param pname Property to get 152 * @return String property from device 153 */ alcGetString(ALCdevice device, int pname)154 public static String alcGetString(ALCdevice device, int pname) { 155 ByteBuffer buffer = nalcGetString(getDevice(device), pname); 156 Util.checkALCError(device); 157 return MemoryUtil.decodeUTF8(buffer); 158 } nalcGetString(long device, int pname)159 static native ByteBuffer nalcGetString(long device, int pname); 160 161 /** 162 * The application can query ALC for information using an integer query function. 163 * For some tokens, <code>null</code> is a legal deviceHandle. In other cases, specifying a <code>null</code> 164 * device will generate an <code>ALC_INVALID_DEVICE</code> error. The application has to 165 * specify the size of the destination buffer provided. A <code>null</code> destination or a zero 166 * size parameter will cause ALC to ignore the query. 167 * 168 * <code>ALC_MAJOR_VERSION</code> - Major version query. 169 * <code>ALC_MINOR_VERSION</code> - Minor version query. 170 * <code>ALC_ATTRIBUTES_SIZE</code> - The size required for the zero-terminated attributes list, 171 * for the current context. <code>null</code> is an invalid device. <code>null</code> (no current context 172 * for the specified device) is legal. 173 * <code>ALC_ALL_ATTRIBUTES</code> - Expects a destination of <code>ALC_CURRENT_ATTRIBUTES_SIZE</code>, 174 * and provides the attribute list for the current context of the specified device. 175 * <code>null</code> is an invalid device. <code>null</code> (no current context for the specified device) 176 * will return the default attributes defined by the specified device. 177 * 178 * @param pname Property to get 179 * @param integerdata ByteBuffer to write integers to 180 */ alcGetInteger(ALCdevice device, int pname, IntBuffer integerdata)181 public static void alcGetInteger(ALCdevice device, int pname, IntBuffer integerdata) { 182 BufferChecks.checkDirect(integerdata); 183 nalcGetIntegerv(getDevice(device), pname, integerdata.remaining(), MemoryUtil.getAddress(integerdata)); 184 Util.checkALCError(device); 185 } nalcGetIntegerv(long device, int pname, int size, long integerdata)186 static native void nalcGetIntegerv(long device, int pname, int size, long integerdata); 187 188 /** 189 * The <code>alcOpenDevice</code> function allows the application (i.e. the client program) to 190 * connect to a device (i.e. the server). 191 * 192 * If the function returns <code>null</code>, then no sound driver/device has been found. The 193 * argument is a null terminated string that requests a certain device or device 194 * configuration. If <code>null</code> is specified, the implementation will provide an 195 * implementation specific default. 196 * 197 * @param devicename name of device to open 198 * @return opened device, or null 199 */ alcOpenDevice(String devicename)200 public static ALCdevice alcOpenDevice(String devicename) { 201 ByteBuffer buffer = MemoryUtil.encodeUTF8(devicename); 202 long device_address = nalcOpenDevice(MemoryUtil.getAddressSafe(buffer)); 203 if(device_address != 0) { 204 ALCdevice device = new ALCdevice(device_address); 205 synchronized (ALC10.devices) { 206 devices.put(device_address, device); 207 } 208 return device; 209 } 210 return null; 211 } nalcOpenDevice(long devicename)212 static native long nalcOpenDevice(long devicename); 213 214 /** 215 * The <code>alcCloseDevice</code> function allows the application (i.e. the client program) to 216 * disconnect from a device (i.e. the server). 217 * 218 * If deviceHandle is <code>null</code> or invalid, an <code>ALC_INVALID_DEVICE</code> error will be 219 * generated. Once closed, a deviceHandle is invalid. 220 * 221 * @param device address of native device to close 222 */ alcCloseDevice(ALCdevice device)223 public static boolean alcCloseDevice(ALCdevice device) { 224 boolean result = nalcCloseDevice(getDevice(device)); 225 synchronized (devices) { 226 device.setInvalid(); 227 devices.remove(new Long(device.device)); 228 } 229 return result; 230 231 } nalcCloseDevice(long device)232 static native boolean nalcCloseDevice(long device); 233 234 /** 235 * A context is created using <code>alcCreateContext</code>. The device parameter has to be a valid 236 * device. The attribute list can be <code>null</code>, or a zero terminated list of integer pairs 237 * composed of valid ALC attribute tokens and requested values. 238 * 239 * Context creation will fail if the application requests attributes that, by themselves, 240 * can not be provided. Context creation will fail if the combination of specified 241 * attributes can not be provided. Context creation will fail if a specified attribute, or 242 * the combination of attributes, does not match the default values for unspecified 243 * attributes. 244 * 245 * @param device address of device to associate context to 246 * @param attrList Buffer to read attributes from 247 * @return New context, or null if creation failed 248 */ alcCreateContext(ALCdevice device, IntBuffer attrList)249 public static ALCcontext alcCreateContext(ALCdevice device, IntBuffer attrList) { 250 long context_address = nalcCreateContext(getDevice(device), MemoryUtil.getAddressSafe(attrList)); 251 Util.checkALCError(device); 252 253 if(context_address != 0) { 254 ALCcontext context = new ALCcontext(context_address); 255 synchronized (ALC10.contexts) { 256 contexts.put(context_address, context); 257 device.addContext(context); 258 } 259 return context; 260 } 261 return null; 262 } nalcCreateContext(long device, long attrList)263 static native long nalcCreateContext(long device, long attrList); 264 265 /** 266 * To make a Context current with respect to AL Operation (state changes by issueing 267 * commands), <code>alcMakeContextCurrent</code> is used. The context parameter can be <code>null</code> 268 * or a valid context pointer. The operation will apply to the device that the context 269 * was created for. 270 * 271 * For each OS process (usually this means for each application), only one context can 272 * be current at any given time. All AL commands apply to the current context. 273 * Commands that affect objects shared among contexts (e.g. buffers) have side effects 274 * on other contexts. 275 * 276 * @param context address of context to make current 277 * @return true if successfull, false if not 278 */ alcMakeContextCurrent(ALCcontext context)279 public static int alcMakeContextCurrent(ALCcontext context) { 280 return nalcMakeContextCurrent(getContext(context)); 281 } nalcMakeContextCurrent(long context)282 static native int nalcMakeContextCurrent(long context); 283 284 /** 285 * The current context is the only context accessible to state changes by AL commands 286 * (aside from state changes affecting shared objects). However, multiple contexts can 287 * be processed at the same time. To indicate that a context should be processed (i.e. 288 * that internal execution state like offset increments are supposed to be performed), 289 * the application has to use <code>alcProcessContext</code>. 290 * 291 * Repeated calls to <code>alcProcessContext</code> are legal, and do not affect a context that is 292 * already marked as processing. The default state of a context created by 293 * alcCreateContext is that it is not marked as processing. 294 */ alcProcessContext(ALCcontext context)295 public static void alcProcessContext(ALCcontext context) { 296 nalcProcessContext(getContext(context)); 297 } nalcProcessContext(long context)298 static native void nalcProcessContext(long context); 299 300 /** 301 * The application can query for, and obtain an handle to, the current context for the 302 * application. If there is no current context, <code>null</code> is returned. 303 * 304 * @return Current ALCcontext 305 */ alcGetCurrentContext()306 public static ALCcontext alcGetCurrentContext() { 307 ALCcontext context = null; 308 long context_address = nalcGetCurrentContext(); 309 if(context_address != 0) { 310 synchronized (ALC10.contexts) { 311 context = ALC10.contexts.get(context_address); 312 } 313 } 314 return context; 315 } nalcGetCurrentContext()316 static native long nalcGetCurrentContext(); 317 318 /** 319 * The application can query for, and obtain an handle to, the device of a given context. 320 * 321 * @param context address of context to get device for 322 */ alcGetContextsDevice(ALCcontext context)323 public static ALCdevice alcGetContextsDevice(ALCcontext context) { 324 ALCdevice device = null; 325 long device_address = nalcGetContextsDevice(getContext(context)); 326 if (device_address != 0) { 327 synchronized (ALC10.devices) { 328 device = ALC10.devices.get(device_address); 329 } 330 } 331 return device; 332 } nalcGetContextsDevice(long context)333 static native long nalcGetContextsDevice(long context); 334 335 /** 336 * The application can suspend any context from processing (including the current 337 * one). To indicate that a context should be suspended from processing (i.e. that 338 * internal execution state like offset increments is not supposed to be changed), the 339 * application has to use <code>alcSuspendContext</code>. 340 * 341 * Repeated calls to <code>alcSuspendContext</code> are legal, and do not affect a context that is 342 * already marked as suspended. The default state of a context created by 343 * <code>alcCreateContext</code> is that it is marked as suspended. 344 * 345 * @param context address of context to suspend 346 */ alcSuspendContext(ALCcontext context)347 public static void alcSuspendContext(ALCcontext context) { 348 nalcSuspendContext(getContext(context)); 349 } nalcSuspendContext(long context)350 static native void nalcSuspendContext(long context); 351 352 /** 353 * The correct way to destroy a context is to first release it using <code>alcMakeCurrent</code> and 354 * <code>null</code>. Applications should not attempt to destroy a current context. 355 * 356 * @param context address of context to Destroy 357 */ alcDestroyContext(ALCcontext context)358 public static void alcDestroyContext(ALCcontext context) { 359 synchronized(ALC10.contexts) { 360 ALCdevice device = alcGetContextsDevice(context); 361 nalcDestroyContext(getContext(context)); 362 device.removeContext(context); 363 context.setInvalid(); 364 } 365 } nalcDestroyContext(long context)366 static native void nalcDestroyContext(long context); 367 368 /** 369 * ALC uses the same conventions and mechanisms as AL for error handling. In 370 * particular, ALC does not use conventions derived from X11 (GLX) or Windows 371 * (WGL). The <code>alcGetError</code> function can be used to query ALC errors. 372 * 373 * Error conditions are specific to the device. 374 * 375 * ALC_NO_ERROR - The device handle or specifier does name an accessible driver/server. 376 * <code>ALC_INVALID_DEVICE</code> - The Context argument does not name a valid context. 377 * <code>ALC_INVALID_CONTEXT</code> - The Context argument does not name a valid context. 378 * <code>ALC_INVALID_ENUM</code> - A token used is not valid, or not applicable. 379 * <code>ALC_INVALID_VALUE</code> - An value (e.g. attribute) is not valid, or not applicable. 380 * 381 * @return Errorcode from ALC statemachine 382 */ alcGetError(ALCdevice device)383 public static int alcGetError(ALCdevice device) { 384 return nalcGetError(getDevice(device)); 385 } nalcGetError(long device)386 static native int nalcGetError(long device); 387 388 /** 389 * Verify that a given extension is available for the current context and the device it 390 * is associated with. 391 * A <code>null</code> name argument returns <code>ALC_FALSE</code>, as do invalid and unsupported string 392 * tokens. 393 * 394 * @param extName name of extension to find 395 * @return true if extension is available, false if not 396 */ alcIsExtensionPresent(ALCdevice device, String extName)397 public static boolean alcIsExtensionPresent(ALCdevice device, String extName) { 398 ByteBuffer buffer = MemoryUtil.encodeASCII(extName); 399 boolean result = nalcIsExtensionPresent(getDevice(device), MemoryUtil.getAddress(buffer)); 400 Util.checkALCError(device); 401 return result; 402 } nalcIsExtensionPresent(long device, long extName)403 private static native boolean nalcIsExtensionPresent(long device, long extName); 404 405 /** 406 * Enumeration/token values are device independend, but tokens defined for 407 * extensions might not be present for a given device. But only the tokens defined 408 * by the AL core are guaranteed. Availability of extension tokens dependends on the ALC extension. 409 * 410 * Specifying a <code>null</code> name parameter will cause an <code>ALC_INVALID_VALUE</code> error. 411 * 412 * @param enumName name of enum to find 413 * @return value of enumeration 414 */ alcGetEnumValue(ALCdevice device, String enumName)415 public static int alcGetEnumValue(ALCdevice device, String enumName) { 416 ByteBuffer buffer = MemoryUtil.encodeASCII(enumName); 417 int result = nalcGetEnumValue(getDevice(device), MemoryUtil.getAddress(buffer)); 418 Util.checkALCError(device); 419 return result; 420 } nalcGetEnumValue(long device, long enumName)421 private static native int nalcGetEnumValue(long device, long enumName); 422 getDevice(ALCdevice device)423 static long getDevice(ALCdevice device) { 424 if(device != null) { 425 Util.checkALCValidDevice(device); 426 return device.device; 427 } 428 return 0L; 429 } 430 getContext(ALCcontext context)431 static long getContext(ALCcontext context) { 432 if(context != null) { 433 Util.checkALCValidContext(context); 434 return context.context; 435 } 436 return 0L; 437 } 438 439 } 440