[17] | 1 | /* -*- mode: C; tab-width:8; c-basic-offset:8 -*- |
---|
| 2 | * vi:set ts=8: |
---|
| 3 | * |
---|
| 4 | * al_state.c |
---|
| 5 | * |
---|
| 6 | * Per-context state management. |
---|
| 7 | * |
---|
| 8 | */ |
---|
| 9 | #include "al_siteconfig.h" |
---|
| 10 | |
---|
| 11 | #include <AL/al.h> |
---|
| 12 | |
---|
| 13 | #include "al_distance.h" |
---|
| 14 | #include "al_error.h" |
---|
| 15 | #include "al_ext.h" |
---|
| 16 | |
---|
| 17 | /* |
---|
| 18 | * A few general remarks about the code below: |
---|
| 19 | * |
---|
| 20 | * * When there is no current context, we set an AL_INVALID_OPERATION. Even |
---|
| 21 | * without a context for recording this error, this is nice for |
---|
| 22 | * debugging. |
---|
| 23 | * |
---|
| 24 | * * As a general contract with the user, we never modify any data via |
---|
| 25 | * pointers if an error condition occurs. |
---|
| 26 | * |
---|
| 27 | * * Getting and locking the context should be done in a single atomic |
---|
| 28 | * operation, but our internal API is not yet capable of this. |
---|
| 29 | * |
---|
| 30 | * * We should somehow hook in the extension mechanism here. |
---|
| 31 | * |
---|
| 32 | */ |
---|
| 33 | |
---|
| 34 | void |
---|
| 35 | alEnable( ALenum param ) |
---|
| 36 | { |
---|
| 37 | AL_context *cc = _alcDCGetContext(); |
---|
| 38 | if( cc == NULL ) { |
---|
| 39 | _alDCSetError( AL_INVALID_OPERATION ); |
---|
| 40 | return; |
---|
| 41 | } |
---|
| 42 | _alcDCLockContext(); |
---|
| 43 | |
---|
| 44 | switch (param) { |
---|
| 45 | default: |
---|
| 46 | _alDCSetError( AL_INVALID_ENUM ); |
---|
| 47 | break; |
---|
| 48 | } |
---|
| 49 | |
---|
| 50 | _alcDCUnlockContext(); |
---|
| 51 | } |
---|
| 52 | |
---|
| 53 | void |
---|
| 54 | alDisable( ALenum param ) |
---|
| 55 | { |
---|
| 56 | AL_context *cc = _alcDCGetContext(); |
---|
| 57 | if( cc == NULL ) { |
---|
| 58 | _alDCSetError( AL_INVALID_OPERATION ); |
---|
| 59 | return; |
---|
| 60 | } |
---|
| 61 | _alcDCLockContext(); |
---|
| 62 | |
---|
| 63 | switch (param) { |
---|
| 64 | default: |
---|
| 65 | _alDCSetError( AL_INVALID_ENUM ); |
---|
| 66 | break; |
---|
| 67 | } |
---|
| 68 | |
---|
| 69 | _alcDCUnlockContext(); |
---|
| 70 | } |
---|
| 71 | |
---|
| 72 | ALboolean |
---|
| 73 | alIsEnabled( ALenum param ) |
---|
| 74 | { |
---|
| 75 | AL_context *cc = _alcDCGetContext(); |
---|
| 76 | if( cc == NULL ) { |
---|
| 77 | _alDCSetError( AL_INVALID_OPERATION ); |
---|
| 78 | return AL_FALSE; |
---|
| 79 | } |
---|
| 80 | _alcDCLockContext(); |
---|
| 81 | |
---|
| 82 | switch (param) { |
---|
| 83 | default: |
---|
| 84 | _alDCSetError( AL_INVALID_ENUM ); |
---|
| 85 | break; |
---|
| 86 | } |
---|
| 87 | |
---|
| 88 | _alcDCUnlockContext(); |
---|
| 89 | return AL_FALSE; |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | const ALchar* |
---|
| 93 | alGetString( ALenum param ) |
---|
| 94 | { |
---|
| 95 | const ALchar *value; |
---|
| 96 | ALchar extensions[1024]; /* TODO: Ugly! */ |
---|
| 97 | |
---|
| 98 | AL_context *cc = _alcDCGetContext(); |
---|
| 99 | if( cc == NULL ) { |
---|
| 100 | _alDCSetError( AL_INVALID_OPERATION ); |
---|
| 101 | return NULL; |
---|
| 102 | } |
---|
| 103 | _alcDCLockContext(); |
---|
| 104 | |
---|
| 105 | switch (param) { |
---|
| 106 | case AL_VERSION: |
---|
| 107 | value = "1.1"; |
---|
| 108 | break; |
---|
| 109 | case AL_RENDERER: |
---|
| 110 | value = "Software"; |
---|
| 111 | break; |
---|
| 112 | case AL_VENDOR: |
---|
| 113 | value = "OpenAL Community"; |
---|
| 114 | break; |
---|
| 115 | case AL_EXTENSIONS: |
---|
| 116 | _alGetExtensionStrings( extensions, sizeof( extensions ) ); |
---|
| 117 | value = extensions; |
---|
| 118 | break; |
---|
| 119 | case AL_NO_ERROR: |
---|
| 120 | value = "No Error"; |
---|
| 121 | break; |
---|
| 122 | case AL_INVALID_NAME: |
---|
| 123 | value = "Invalid Name"; |
---|
| 124 | break; |
---|
| 125 | case AL_INVALID_ENUM: |
---|
| 126 | value = "Invalid Enum"; |
---|
| 127 | break; |
---|
| 128 | case AL_INVALID_VALUE: |
---|
| 129 | value = "Invalid Value"; |
---|
| 130 | break; |
---|
| 131 | case AL_INVALID_OPERATION: |
---|
| 132 | value = "Invalid Operation"; |
---|
| 133 | break; |
---|
| 134 | case AL_OUT_OF_MEMORY: |
---|
| 135 | value = "Out of Memory"; |
---|
| 136 | break; |
---|
| 137 | default: |
---|
| 138 | value = NULL; |
---|
| 139 | _alDCSetError( AL_INVALID_ENUM ); |
---|
| 140 | break; |
---|
| 141 | } |
---|
| 142 | |
---|
| 143 | _alcDCUnlockContext(); |
---|
| 144 | return value; |
---|
| 145 | } |
---|
| 146 | |
---|
| 147 | #define MAX_DATA_ENTRIES_FILLED 1 |
---|
| 148 | |
---|
| 149 | /* everything is better than code duplication, even macros... */ |
---|
| 150 | |
---|
| 151 | #define DEFINE_GETTER(type,conv,namev,name) \ |
---|
| 152 | void \ |
---|
| 153 | namev( ALenum param, type *data ) \ |
---|
| 154 | { \ |
---|
| 155 | AL_context *cc = _alcDCGetContext(); \ |
---|
| 156 | if( cc == NULL ) { \ |
---|
| 157 | _alDCSetError( AL_INVALID_OPERATION ); \ |
---|
| 158 | return; \ |
---|
| 159 | } \ |
---|
| 160 | _alcDCLockContext(); \ |
---|
| 161 | \ |
---|
| 162 | switch( param ) { \ |
---|
| 163 | case AL_DOPPLER_FACTOR: \ |
---|
| 164 | data[0] = conv(cc->doppler_factor); \ |
---|
| 165 | break; \ |
---|
| 166 | case AL_DOPPLER_VELOCITY: \ |
---|
| 167 | data[0] = conv(cc->doppler_velocity); \ |
---|
| 168 | break; \ |
---|
| 169 | case AL_SPEED_OF_SOUND: \ |
---|
| 170 | data[0] = conv(cc->speed_of_sound); \ |
---|
| 171 | break; \ |
---|
| 172 | case AL_DISTANCE_MODEL: \ |
---|
| 173 | data[0] = conv(cc->distance_model); \ |
---|
| 174 | break; \ |
---|
| 175 | default: \ |
---|
| 176 | _alDCSetError( AL_INVALID_ENUM ); \ |
---|
| 177 | break; \ |
---|
| 178 | } \ |
---|
| 179 | \ |
---|
| 180 | _alcDCUnlockContext(); \ |
---|
| 181 | } \ |
---|
| 182 | \ |
---|
| 183 | type \ |
---|
| 184 | name( ALenum param ) \ |
---|
| 185 | { \ |
---|
| 186 | type buf[MAX_DATA_ENTRIES_FILLED]; \ |
---|
| 187 | namev(param, buf); \ |
---|
| 188 | return buf[0]; \ |
---|
| 189 | } |
---|
| 190 | |
---|
| 191 | #define CONV_BOOLEAN(x) ((x) ? AL_TRUE : AL_FALSE) |
---|
| 192 | #define CONV_INTEGER(x) ((ALint)(x)) |
---|
| 193 | #define CONV_FLOAT(x) ((ALfloat)(x)) |
---|
| 194 | #define CONV_DOUBLE(x) ((ALdouble)(x)) |
---|
| 195 | |
---|
| 196 | DEFINE_GETTER(ALboolean,CONV_BOOLEAN,alGetBooleanv,alGetBoolean) |
---|
| 197 | DEFINE_GETTER(ALint,CONV_INTEGER,alGetIntegerv,alGetInteger) |
---|
| 198 | DEFINE_GETTER(ALfloat,CONV_FLOAT,alGetFloatv,alGetFloat) |
---|
| 199 | DEFINE_GETTER(ALdouble,CONV_DOUBLE,alGetDoublev,alGetDouble) |
---|
| 200 | |
---|
| 201 | #undef DEFINE_GETTER |
---|
| 202 | |
---|
| 203 | void |
---|
| 204 | alDopplerFactor( ALfloat value ) |
---|
| 205 | { |
---|
| 206 | AL_context *cc = _alcDCGetContext(); |
---|
| 207 | if( cc == NULL ) { |
---|
| 208 | _alDCSetError( AL_INVALID_OPERATION ); |
---|
| 209 | return; |
---|
| 210 | } |
---|
| 211 | _alcDCLockContext(); |
---|
| 212 | |
---|
| 213 | if( value < 0.0f ) { |
---|
| 214 | _alDCSetError( AL_INVALID_VALUE ); |
---|
| 215 | _alcDCUnlockContext(); |
---|
| 216 | return; |
---|
| 217 | } |
---|
| 218 | cc->doppler_factor = value; |
---|
| 219 | |
---|
| 220 | _alcDCUnlockContext(); |
---|
| 221 | } |
---|
| 222 | |
---|
| 223 | void |
---|
| 224 | alDopplerVelocity( ALfloat value ) |
---|
| 225 | { |
---|
| 226 | AL_context *cc = _alcDCGetContext(); |
---|
| 227 | if( cc == NULL ) { |
---|
| 228 | _alDCSetError( AL_INVALID_OPERATION ); |
---|
| 229 | return; |
---|
| 230 | } |
---|
| 231 | _alcDCLockContext(); |
---|
| 232 | |
---|
| 233 | if( value <= 0.0f ) { |
---|
| 234 | _alDCSetError( AL_INVALID_VALUE ); |
---|
| 235 | _alcDCUnlockContext(); |
---|
| 236 | return; |
---|
| 237 | } |
---|
| 238 | cc->doppler_velocity = value; |
---|
| 239 | |
---|
| 240 | _alcDCUnlockContext(); |
---|
| 241 | } |
---|
| 242 | |
---|
| 243 | void |
---|
| 244 | alSpeedOfSound( ALfloat value ) |
---|
| 245 | { |
---|
| 246 | AL_context *cc = _alcDCGetContext(); |
---|
| 247 | if( cc == NULL ) { |
---|
| 248 | _alDCSetError( AL_INVALID_OPERATION ); |
---|
| 249 | return; |
---|
| 250 | } |
---|
| 251 | _alcDCLockContext(); |
---|
| 252 | |
---|
| 253 | if( value <= 0.0f ) { |
---|
| 254 | _alDCSetError( AL_INVALID_VALUE ); |
---|
| 255 | _alcDCUnlockContext(); |
---|
| 256 | return; |
---|
| 257 | } |
---|
| 258 | cc->speed_of_sound = value; |
---|
| 259 | |
---|
| 260 | _alcDCUnlockContext(); |
---|
| 261 | } |
---|
| 262 | |
---|
| 263 | void |
---|
| 264 | alDistanceModel( ALenum distanceModel ) |
---|
| 265 | { |
---|
| 266 | AL_context *cc = _alcDCGetContext(); |
---|
| 267 | if( cc == NULL ) { |
---|
| 268 | _alDCSetError( AL_INVALID_OPERATION ); |
---|
| 269 | return; |
---|
| 270 | } |
---|
| 271 | _alcDCLockContext(); |
---|
| 272 | |
---|
| 273 | switch( distanceModel ) { |
---|
| 274 | case AL_NONE: |
---|
| 275 | case AL_INVERSE_DISTANCE: |
---|
| 276 | case AL_INVERSE_DISTANCE_CLAMPED: |
---|
| 277 | case AL_LINEAR_DISTANCE: |
---|
| 278 | case AL_LINEAR_DISTANCE_CLAMPED: |
---|
| 279 | case AL_EXPONENT_DISTANCE: |
---|
| 280 | case AL_EXPONENT_DISTANCE_CLAMPED: |
---|
| 281 | cc->distance_model = distanceModel; |
---|
| 282 | _alUpdateDistanceModel(cc); |
---|
| 283 | break; |
---|
| 284 | default: |
---|
| 285 | _alDCSetError( AL_INVALID_ENUM ); |
---|
| 286 | break; |
---|
| 287 | } |
---|
| 288 | |
---|
| 289 | _alcDCUnlockContext(); |
---|
| 290 | } |
---|