diff options
Diffstat (limited to 'utils/openal-info.c')
-rw-r--r-- | utils/openal-info.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/utils/openal-info.c b/utils/openal-info.c new file mode 100644 index 00000000..586a1c73 --- /dev/null +++ b/utils/openal-info.c @@ -0,0 +1,332 @@ +/* + * OpenAL Info Utility + * + * Copyright (c) 2010 by Chris Robinson <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "config.h" + +#include <stdio.h> +#include <string.h> + +#include "AL/alc.h" +#include "AL/al.h" +#include "AL/alext.h" + +#ifndef ALC_ENUMERATE_ALL_EXT +#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 +#define ALC_ALL_DEVICES_SPECIFIER 0x1013 +#endif + +#ifndef ALC_EXT_EFX +#define ALC_EFX_MAJOR_VERSION 0x20001 +#define ALC_EFX_MINOR_VERSION 0x20002 +#define ALC_MAX_AUXILIARY_SENDS 0x20003 +#define AL_FILTER_TYPE 0x8001 +#define AL_FILTER_NULL 0x0000 +#define AL_FILTER_LOWPASS 0x0001 +#define AL_FILTER_HIGHPASS 0x0002 +#define AL_FILTER_BANDPASS 0x0003 +#define AL_EFFECT_TYPE 0x8001 +#define AL_EFFECT_NULL 0x0000 +#define AL_EFFECT_EAXREVERB 0x8000 +#define AL_EFFECT_REVERB 0x0001 +#define AL_EFFECT_CHORUS 0x0002 +#define AL_EFFECT_DISTORTION 0x0003 +#define AL_EFFECT_ECHO 0x0004 +#define AL_EFFECT_FLANGER 0x0005 +#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 +#define AL_EFFECT_VOCAL_MORPHER 0x0007 +#define AL_EFFECT_PITCH_SHIFTER 0x0008 +#define AL_EFFECT_RING_MODULATOR 0x0009 +#define AL_EFFECT_AUTOWAH 0x000A +#define AL_EFFECT_COMPRESSOR 0x000B +#define AL_EFFECT_EQUALIZER 0x000C +typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); +typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); +#endif +static LPALGENFILTERS palGenFilters; +static LPALDELETEFILTERS palDeleteFilters; +static LPALFILTERI palFilteri; +static LPALGENEFFECTS palGenEffects; +static LPALDELETEEFFECTS palDeleteEffects; +static LPALEFFECTI palEffecti; + + +#define MAX_WIDTH 80 + +static void printList(const char *list, char separator) +{ + size_t col = MAX_WIDTH, len; + const char *indent = " "; + const char *next; + + if(!list || *list == '\0') + { + fprintf(stdout, "\n%s!!! none !!!\n", indent); + return; + } + + do { + next = strchr(list, separator); + if(next) + { + len = next-list; + do { + next++; + } while(*next == separator); + } + else + len = strlen(list); + + if(len + col + 2 >= MAX_WIDTH) + { + fprintf(stdout, "\n%s", indent); + col = strlen(indent); + } + else + { + fputc(' ', stdout); + col++; + } + + len = fwrite(list, 1, len, stdout); + col += len; + + if(!next || *next == '\0') + break; + fputc(',', stdout); + col++; + + list = next; + } while(1); + fputc('\n', stdout); +} + +static void printDeviceList(const char *list) +{ + if(!list || *list == '\0') + printf(" !!! none !!!\n"); + else do { + printf(" %s\n", list); + list += strlen(list) + 1; + } while(*list != '\0'); +} + + +static ALenum checkALErrors(int linenum) +{ + ALenum err = alGetError(); + if(err != AL_NO_ERROR) + printf("OpenAL Error: %s (0x%x), @ %d\n", alGetString(err), err, linenum); + return err; +} +#define checkALErrors() checkALErrors(__LINE__) + +static ALCenum checkALCErrors(ALCdevice *device, int linenum) +{ + ALCenum err = alcGetError(device); + if(err != ALC_NO_ERROR) + printf("ALC Error: %s (0x%x), @ %d\n", alcGetString(device, err), err, linenum); + return err; +} +#define checkALCErrors(x) checkALCErrors((x),__LINE__) + + +static void printALCInfo(ALCdevice *device) +{ + ALCint major, minor; + + alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); + alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor); + if(checkALCErrors(device) == ALC_NO_ERROR) + printf("ALC version: %d.%d\n", major, minor); + if(device) + { + printf("ALC extensions:"); + printList(alcGetString(device, ALC_EXTENSIONS), ' '); + checkALCErrors(device); + } +} + +static void printALInfo(void) +{ + printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR)); + printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER)); + printf("OpenAL version string: %s\n", alGetString(AL_VERSION)); + printf("OpenAL extensions:"); + printList(alGetString(AL_EXTENSIONS), ' '); + checkALErrors(); +} + +static void printEFXInfo(ALCdevice *device) +{ + ALCint major, minor, sends; + ALuint obj; + int i; + const ALenum filters[] = { + AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS, + AL_FILTER_NULL + }; + char filterNames[] = "Low-pass,High-pass,Band-pass,"; + const ALenum effects[] = { + AL_EFFECT_EAXREVERB, AL_EFFECT_REVERB, AL_EFFECT_CHORUS, + AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER, + AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER, + AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR, AL_EFFECT_AUTOWAH, + AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER, AL_EFFECT_NULL + }; + char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger," + "Frequency Shifter,Vocal Morpher,Pitch Shifter," + "Ring Modulator,Autowah,Compressor,Equalizer,"; + char *current; + + if(alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_FALSE) + { + printf("EFX not available\n"); + return; + } + + alcGetIntegerv(device, ALC_EFX_MAJOR_VERSION, 1, &major); + alcGetIntegerv(device, ALC_EFX_MINOR_VERSION, 1, &minor); + if(checkALCErrors(device) == ALC_NO_ERROR) + printf("EFX version: %d.%d\n", major, minor); + alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends); + if(checkALCErrors(device) == ALC_NO_ERROR) + printf("Max auxiliary sends: %d\n", sends); + + palGenFilters = alGetProcAddress("alGenFilters"); + palDeleteFilters = alGetProcAddress("alDeleteFilters"); + palFilteri = alGetProcAddress("alFilteri"); + palGenEffects = alGetProcAddress("alGenEffects"); + palDeleteEffects = alGetProcAddress("alDeleteEffects"); + palEffecti = alGetProcAddress("alEffecti"); + if(checkALErrors() != AL_NO_ERROR || + !palGenFilters || !palDeleteFilters || !palFilteri || + !palGenEffects || !palDeleteEffects || !palEffecti) + { + printf("!!! Missing EFX functions !!!\n"); + return; + } + + palGenFilters(1, &obj); + if(checkALErrors() == AL_NO_ERROR) + { + current = filterNames; + for(i = 0;filters[i] != AL_FILTER_NULL;i++) + { + char *next = strchr(current, ','); + + palFilteri(obj, AL_FILTER_TYPE, filters[i]); + if(alGetError() == AL_NO_ERROR) + current = next+1; + else + memmove(current, next+1, strlen(next)); + } + palDeleteFilters(1, &obj); + checkALErrors(); + + printf("Supported filters:"); + printList(filterNames, ','); + } + + palGenEffects(1, &obj); + if(checkALErrors() == AL_NO_ERROR) + { + current = effectNames; + for(i = 0;effects[i] != AL_EFFECT_NULL;i++) + { + char *next = strchr(current, ','); + + palEffecti(obj, AL_EFFECT_TYPE, effects[i]); + if(alGetError() == AL_NO_ERROR) + current = next+1; + else + memmove(current, next+1, strlen(next)); + } + palDeleteEffects(1, &obj); + checkALErrors(); + + printf("Supported effects:"); + printList(effectNames, ','); + } +} + +int main(int argc, char *argv[]) +{ + ALCdevice *device; + ALCcontext *context; + + if(argc > 1 && (strcmp(argv[1], "--help") == 0 || + strcmp(argv[1], "-h") == 0)) + { + printf("Usage: %s [playback device]\n", argv[0]); + return 0; + } + + printf("Available playback devices:\n"); + if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE) + printDeviceList(alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER)); + else + printDeviceList(alcGetString(NULL, ALC_DEVICE_SPECIFIER)); + printf("Available capture devices:\n"); + printDeviceList(alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)); + + printf("Default playback device: %s\n", + alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)); + printf("Default capture device: %s\n", + alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)); + + printALCInfo(NULL); + + device = alcOpenDevice((argc>1) ? argv[1] : NULL); + if(!device) + { + printf("\n!!! Failed to open %s !!!\n\n", ((argc>1) ? argv[1] : "default device")); + return 1; + } + + printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER)); + printALCInfo(device); + + context = alcCreateContext(device, NULL); + if(!context || alcMakeContextCurrent(context) == ALC_FALSE) + { + if(context) + alcDestroyContext(context); + alcCloseDevice(device); + printf("\n!!! Failed to set a context !!!\n\n"); + return 1; + } + + printALInfo(); + printEFXInfo(device); + + alcMakeContextCurrent(NULL); + alcDestroyContext(context); + alcCloseDevice(device); + + return 0; +} |