annotate utils/openal-info.c @ 0:f9476ff7637e

initial forking of open-al to create multiple listeners
author Robert McIntyre <rlm@mit.edu>
date Tue, 25 Oct 2011 13:02:31 -0700
parents
children
rev   line source
rlm@0 1 /*
rlm@0 2 * OpenAL Info Utility
rlm@0 3 *
rlm@0 4 * Copyright (c) 2010 by Chris Robinson <chris.kcat@gmail.com>
rlm@0 5 *
rlm@0 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
rlm@0 7 * of this software and associated documentation files (the "Software"), to deal
rlm@0 8 * in the Software without restriction, including without limitation the rights
rlm@0 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
rlm@0 10 * copies of the Software, and to permit persons to whom the Software is
rlm@0 11 * furnished to do so, subject to the following conditions:
rlm@0 12 *
rlm@0 13 * The above copyright notice and this permission notice shall be included in
rlm@0 14 * all copies or substantial portions of the Software.
rlm@0 15 *
rlm@0 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
rlm@0 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
rlm@0 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
rlm@0 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
rlm@0 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
rlm@0 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
rlm@0 22 * THE SOFTWARE.
rlm@0 23 */
rlm@0 24
rlm@0 25 #include <stdio.h>
rlm@0 26 #include <string.h>
rlm@0 27
rlm@0 28 #include "AL/alc.h"
rlm@0 29 #include "AL/al.h"
rlm@0 30 #include "AL/alext.h"
rlm@0 31
rlm@0 32 #ifndef ALC_ENUMERATE_ALL_EXT
rlm@0 33 #define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
rlm@0 34 #define ALC_ALL_DEVICES_SPECIFIER 0x1013
rlm@0 35 #endif
rlm@0 36
rlm@0 37 #ifndef ALC_EXT_EFX
rlm@0 38 #define ALC_EFX_MAJOR_VERSION 0x20001
rlm@0 39 #define ALC_EFX_MINOR_VERSION 0x20002
rlm@0 40 #define ALC_MAX_AUXILIARY_SENDS 0x20003
rlm@0 41 #define AL_FILTER_TYPE 0x8001
rlm@0 42 #define AL_FILTER_NULL 0x0000
rlm@0 43 #define AL_FILTER_LOWPASS 0x0001
rlm@0 44 #define AL_FILTER_HIGHPASS 0x0002
rlm@0 45 #define AL_FILTER_BANDPASS 0x0003
rlm@0 46 #define AL_EFFECT_TYPE 0x8001
rlm@0 47 #define AL_EFFECT_NULL 0x0000
rlm@0 48 #define AL_EFFECT_EAXREVERB 0x8000
rlm@0 49 #define AL_EFFECT_REVERB 0x0001
rlm@0 50 #define AL_EFFECT_CHORUS 0x0002
rlm@0 51 #define AL_EFFECT_DISTORTION 0x0003
rlm@0 52 #define AL_EFFECT_ECHO 0x0004
rlm@0 53 #define AL_EFFECT_FLANGER 0x0005
rlm@0 54 #define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
rlm@0 55 #define AL_EFFECT_VOCAL_MORPHER 0x0007
rlm@0 56 #define AL_EFFECT_PITCH_SHIFTER 0x0008
rlm@0 57 #define AL_EFFECT_RING_MODULATOR 0x0009
rlm@0 58 #define AL_EFFECT_AUTOWAH 0x000A
rlm@0 59 #define AL_EFFECT_COMPRESSOR 0x000B
rlm@0 60 #define AL_EFFECT_EQUALIZER 0x000C
rlm@0 61 typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
rlm@0 62 typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*);
rlm@0 63 typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
rlm@0 64 typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
rlm@0 65 typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*);
rlm@0 66 typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
rlm@0 67 #endif
rlm@0 68 static LPALGENFILTERS palGenFilters;
rlm@0 69 static LPALDELETEFILTERS palDeleteFilters;
rlm@0 70 static LPALFILTERI palFilteri;
rlm@0 71 static LPALGENEFFECTS palGenEffects;
rlm@0 72 static LPALDELETEEFFECTS palDeleteEffects;
rlm@0 73 static LPALEFFECTI palEffecti;
rlm@0 74
rlm@0 75 #ifndef ALC_EXT_DEDICATED
rlm@0 76 #define AL_EFFECT_DEDICATED_DIALOGUE 0x9001
rlm@0 77 #define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000
rlm@0 78 #endif
rlm@0 79
rlm@0 80
rlm@0 81 #define MAX_WIDTH 80
rlm@0 82
rlm@0 83 static void printList(const char *list, char separator)
rlm@0 84 {
rlm@0 85 size_t col = MAX_WIDTH, len;
rlm@0 86 const char *indent = " ";
rlm@0 87 const char *next;
rlm@0 88
rlm@0 89 if(!list || *list == '\0')
rlm@0 90 {
rlm@0 91 fprintf(stdout, "\n%s!!! none !!!\n", indent);
rlm@0 92 return;
rlm@0 93 }
rlm@0 94
rlm@0 95 do {
rlm@0 96 next = strchr(list, separator);
rlm@0 97 if(next)
rlm@0 98 {
rlm@0 99 len = next-list;
rlm@0 100 do {
rlm@0 101 next++;
rlm@0 102 } while(*next == separator);
rlm@0 103 }
rlm@0 104 else
rlm@0 105 len = strlen(list);
rlm@0 106
rlm@0 107 if(len + col + 2 >= MAX_WIDTH)
rlm@0 108 {
rlm@0 109 fprintf(stdout, "\n%s", indent);
rlm@0 110 col = strlen(indent);
rlm@0 111 }
rlm@0 112 else
rlm@0 113 {
rlm@0 114 fputc(' ', stdout);
rlm@0 115 col++;
rlm@0 116 }
rlm@0 117
rlm@0 118 len = fwrite(list, 1, len, stdout);
rlm@0 119 col += len;
rlm@0 120
rlm@0 121 if(!next || *next == '\0')
rlm@0 122 break;
rlm@0 123 fputc(',', stdout);
rlm@0 124 col++;
rlm@0 125
rlm@0 126 list = next;
rlm@0 127 } while(1);
rlm@0 128 fputc('\n', stdout);
rlm@0 129 }
rlm@0 130
rlm@0 131 static void printDeviceList(const char *list)
rlm@0 132 {
rlm@0 133 if(!list || *list == '\0')
rlm@0 134 printf(" !!! none !!!\n");
rlm@0 135 else do {
rlm@0 136 printf(" %s\n", list);
rlm@0 137 list += strlen(list) + 1;
rlm@0 138 } while(*list != '\0');
rlm@0 139 }
rlm@0 140
rlm@0 141
rlm@0 142 static ALenum checkALErrors(int linenum)
rlm@0 143 {
rlm@0 144 ALenum err = alGetError();
rlm@0 145 if(err != AL_NO_ERROR)
rlm@0 146 printf("OpenAL Error: %s (0x%x), @ %d\n", alGetString(err), err, linenum);
rlm@0 147 return err;
rlm@0 148 }
rlm@0 149 #define checkALErrors() checkALErrors(__LINE__)
rlm@0 150
rlm@0 151 static ALCenum checkALCErrors(ALCdevice *device, int linenum)
rlm@0 152 {
rlm@0 153 ALCenum err = alcGetError(device);
rlm@0 154 if(err != ALC_NO_ERROR)
rlm@0 155 printf("ALC Error: %s (0x%x), @ %d\n", alcGetString(device, err), err, linenum);
rlm@0 156 return err;
rlm@0 157 }
rlm@0 158 #define checkALCErrors(x) checkALCErrors((x),__LINE__)
rlm@0 159
rlm@0 160
rlm@0 161 static void printALCInfo(ALCdevice *device)
rlm@0 162 {
rlm@0 163 ALCint major, minor;
rlm@0 164
rlm@0 165 alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
rlm@0 166 alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor);
rlm@0 167 if(checkALCErrors(device) == ALC_NO_ERROR)
rlm@0 168 printf("ALC version: %d.%d\n", major, minor);
rlm@0 169 if(device)
rlm@0 170 {
rlm@0 171 printf("ALC extensions:");
rlm@0 172 printList(alcGetString(device, ALC_EXTENSIONS), ' ');
rlm@0 173 checkALCErrors(device);
rlm@0 174 }
rlm@0 175 }
rlm@0 176
rlm@0 177 static void printALInfo(void)
rlm@0 178 {
rlm@0 179 printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
rlm@0 180 printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER));
rlm@0 181 printf("OpenAL version string: %s\n", alGetString(AL_VERSION));
rlm@0 182 printf("OpenAL extensions:");
rlm@0 183 printList(alGetString(AL_EXTENSIONS), ' ');
rlm@0 184 checkALErrors();
rlm@0 185 }
rlm@0 186
rlm@0 187 static void printEFXInfo(ALCdevice *device)
rlm@0 188 {
rlm@0 189 ALCint major, minor, sends;
rlm@0 190 ALuint obj;
rlm@0 191 int i;
rlm@0 192 const ALenum filters[] = {
rlm@0 193 AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS,
rlm@0 194 AL_FILTER_NULL
rlm@0 195 };
rlm@0 196 char filterNames[] = "Low-pass,High-pass,Band-pass,";
rlm@0 197 const ALenum effects[] = {
rlm@0 198 AL_EFFECT_EAXREVERB, AL_EFFECT_REVERB, AL_EFFECT_CHORUS,
rlm@0 199 AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER,
rlm@0 200 AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER,
rlm@0 201 AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR, AL_EFFECT_AUTOWAH,
rlm@0 202 AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER, AL_EFFECT_NULL
rlm@0 203 };
rlm@0 204 const ALenum dedeffects[] = {
rlm@0 205 AL_EFFECT_DEDICATED_DIALOGUE,
rlm@0 206 AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, AL_EFFECT_NULL
rlm@0 207 };
rlm@0 208 char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger,"
rlm@0 209 "Frequency Shifter,Vocal Morpher,Pitch Shifter,"
rlm@0 210 "Ring Modulator,Autowah,Compressor,Equalizer,"
rlm@0 211 "Dedicated Dialog,Dedicated LFE,";
rlm@0 212 char *current;
rlm@0 213
rlm@0 214 if(alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_FALSE)
rlm@0 215 {
rlm@0 216 printf("EFX not available\n");
rlm@0 217 return;
rlm@0 218 }
rlm@0 219
rlm@0 220 alcGetIntegerv(device, ALC_EFX_MAJOR_VERSION, 1, &major);
rlm@0 221 alcGetIntegerv(device, ALC_EFX_MINOR_VERSION, 1, &minor);
rlm@0 222 if(checkALCErrors(device) == ALC_NO_ERROR)
rlm@0 223 printf("EFX version: %d.%d\n", major, minor);
rlm@0 224 alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends);
rlm@0 225 if(checkALCErrors(device) == ALC_NO_ERROR)
rlm@0 226 printf("Max auxiliary sends: %d\n", sends);
rlm@0 227
rlm@0 228 palGenFilters = alGetProcAddress("alGenFilters");
rlm@0 229 palDeleteFilters = alGetProcAddress("alDeleteFilters");
rlm@0 230 palFilteri = alGetProcAddress("alFilteri");
rlm@0 231 palGenEffects = alGetProcAddress("alGenEffects");
rlm@0 232 palDeleteEffects = alGetProcAddress("alDeleteEffects");
rlm@0 233 palEffecti = alGetProcAddress("alEffecti");
rlm@0 234 if(checkALErrors() != AL_NO_ERROR ||
rlm@0 235 !palGenFilters || !palDeleteFilters || !palFilteri ||
rlm@0 236 !palGenEffects || !palDeleteEffects || !palEffecti)
rlm@0 237 {
rlm@0 238 printf("!!! Missing EFX functions !!!\n");
rlm@0 239 return;
rlm@0 240 }
rlm@0 241
rlm@0 242 palGenFilters(1, &obj);
rlm@0 243 if(checkALErrors() == AL_NO_ERROR)
rlm@0 244 {
rlm@0 245 current = filterNames;
rlm@0 246 for(i = 0;filters[i] != AL_FILTER_NULL;i++)
rlm@0 247 {
rlm@0 248 char *next = strchr(current, ',');
rlm@0 249
rlm@0 250 palFilteri(obj, AL_FILTER_TYPE, filters[i]);
rlm@0 251 if(alGetError() == AL_NO_ERROR)
rlm@0 252 current = next+1;
rlm@0 253 else
rlm@0 254 memmove(current, next+1, strlen(next));
rlm@0 255 }
rlm@0 256 palDeleteFilters(1, &obj);
rlm@0 257 checkALErrors();
rlm@0 258
rlm@0 259 printf("Supported filters:");
rlm@0 260 printList(filterNames, ',');
rlm@0 261 }
rlm@0 262
rlm@0 263 palGenEffects(1, &obj);
rlm@0 264 if(checkALErrors() == AL_NO_ERROR)
rlm@0 265 {
rlm@0 266 current = effectNames;
rlm@0 267 for(i = 0;effects[i] != AL_EFFECT_NULL;i++)
rlm@0 268 {
rlm@0 269 char *next = strchr(current, ',');
rlm@0 270
rlm@0 271 palEffecti(obj, AL_EFFECT_TYPE, effects[i]);
rlm@0 272 if(alGetError() == AL_NO_ERROR)
rlm@0 273 current = next+1;
rlm@0 274 else
rlm@0 275 memmove(current, next+1, strlen(next));
rlm@0 276 }
rlm@0 277 if(alcIsExtensionPresent(device, "ALC_EXT_DEDICATED"))
rlm@0 278 {
rlm@0 279 for(i = 0;dedeffects[i] != AL_EFFECT_NULL;i++)
rlm@0 280 {
rlm@0 281 char *next = strchr(current, ',');
rlm@0 282
rlm@0 283 palEffecti(obj, AL_EFFECT_TYPE, dedeffects[i]);
rlm@0 284 if(alGetError() == AL_NO_ERROR)
rlm@0 285 current = next+1;
rlm@0 286 else
rlm@0 287 memmove(current, next+1, strlen(next));
rlm@0 288 }
rlm@0 289 }
rlm@0 290 else
rlm@0 291 {
rlm@0 292 for(i = 0;dedeffects[i] != AL_EFFECT_NULL;i++)
rlm@0 293 {
rlm@0 294 char *next = strchr(current, ',');
rlm@0 295 memmove(current, next+1, strlen(next));
rlm@0 296 }
rlm@0 297 }
rlm@0 298 palDeleteEffects(1, &obj);
rlm@0 299 checkALErrors();
rlm@0 300
rlm@0 301 printf("Supported effects:");
rlm@0 302 printList(effectNames, ',');
rlm@0 303 }
rlm@0 304 }
rlm@0 305
rlm@0 306 int main(int argc, char *argv[])
rlm@0 307 {
rlm@0 308 ALCdevice *device;
rlm@0 309 ALCcontext *context;
rlm@0 310
rlm@0 311 if(argc > 1 && (strcmp(argv[1], "--help") == 0 ||
rlm@0 312 strcmp(argv[1], "-h") == 0))
rlm@0 313 {
rlm@0 314 printf("Usage: %s [playback device]\n", argv[0]);
rlm@0 315 return 0;
rlm@0 316 }
rlm@0 317
rlm@0 318 printf("Available playback devices:\n");
rlm@0 319 if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
rlm@0 320 printDeviceList(alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER));
rlm@0 321 else
rlm@0 322 printDeviceList(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
rlm@0 323 printf("Available capture devices:\n");
rlm@0 324 printDeviceList(alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER));
rlm@0 325
rlm@0 326 if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
rlm@0 327 printf("Default playback device: %s\n",
rlm@0 328 alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER));
rlm@0 329 else
rlm@0 330 printf("Default playback device: %s\n",
rlm@0 331 alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
rlm@0 332 printf("Default capture device: %s\n",
rlm@0 333 alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
rlm@0 334
rlm@0 335 printALCInfo(NULL);
rlm@0 336
rlm@0 337 device = alcOpenDevice((argc>1) ? argv[1] : NULL);
rlm@0 338 if(!device)
rlm@0 339 {
rlm@0 340 printf("\n!!! Failed to open %s !!!\n\n", ((argc>1) ? argv[1] : "default device"));
rlm@0 341 return 1;
rlm@0 342 }
rlm@0 343
rlm@0 344 printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
rlm@0 345 printALCInfo(device);
rlm@0 346
rlm@0 347 context = alcCreateContext(device, NULL);
rlm@0 348 if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
rlm@0 349 {
rlm@0 350 if(context)
rlm@0 351 alcDestroyContext(context);
rlm@0 352 alcCloseDevice(device);
rlm@0 353 printf("\n!!! Failed to set a context !!!\n\n");
rlm@0 354 return 1;
rlm@0 355 }
rlm@0 356
rlm@0 357 printALInfo();
rlm@0 358 printEFXInfo(device);
rlm@0 359
rlm@0 360 alcMakeContextCurrent(NULL);
rlm@0 361 alcDestroyContext(context);
rlm@0 362 alcCloseDevice(device);
rlm@0 363
rlm@0 364 return 0;
rlm@0 365 }