4 * Copyright (c) 2010 by Chris Robinson <chris.kcat@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34 #include "win_main_utf8.h"
37 #ifndef ALC_ENUMERATE_ALL_EXT
38 #define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
39 #define ALC_ALL_DEVICES_SPECIFIER 0x1013
43 #define ALC_EFX_MAJOR_VERSION 0x20001
44 #define ALC_EFX_MINOR_VERSION 0x20002
45 #define ALC_MAX_AUXILIARY_SENDS 0x20003
50 #define WIN32_LEAN_AND_MEAN
53 static WCHAR
*FromUTF8(const char *str
)
58 if((len
=MultiByteToWideChar(CP_UTF8
, 0, str
, -1, NULL
, 0)) > 0)
60 out
= calloc(sizeof(WCHAR
), (unsigned int)(len
));
61 MultiByteToWideChar(CP_UTF8
, 0, str
, -1, out
, len
);
66 /* Override printf, fprintf, and fwrite so we can print UTF-8 strings. */
67 static void al_fprintf(FILE *file
, const char *fmt
, ...)
74 vsnprintf(str
, sizeof(str
), fmt
, ap
);
77 str
[sizeof(str
)-1] = 0;
80 fprintf(file
, "<UTF-8 error> %s", str
);
82 fprintf(file
, "%ls", wstr
);
85 #define fprintf al_fprintf
86 #define printf(...) al_fprintf(stdout, __VA_ARGS__)
88 static size_t al_fwrite(const void *ptr
, size_t size
, size_t nmemb
, FILE *file
)
95 if(len
> sizeof(str
)-1)
97 memcpy(str
, ptr
, len
);
100 wstr
= FromUTF8(str
);
102 fprintf(file
, "<UTF-8 error> %s", str
);
104 fprintf(file
, "%ls", wstr
);
109 #define fwrite al_fwrite
115 static void printList(const char *list
, char separator
)
117 size_t col
= MAX_WIDTH
, len
;
118 const char *indent
= " ";
121 if(!list
|| *list
== '\0')
123 fprintf(stdout
, "\n%s!!! none !!!\n", indent
);
128 next
= strchr(list
, separator
);
131 len
= (size_t)(next
-list
);
134 } while(*next
== separator
);
139 if(len
+ col
+ 2 >= MAX_WIDTH
)
141 fprintf(stdout
, "\n%s", indent
);
142 col
= strlen(indent
);
150 len
= fwrite(list
, 1, len
, stdout
);
153 if(!next
|| *next
== '\0')
163 static void printDeviceList(const char *list
)
165 if(!list
|| *list
== '\0')
166 printf(" !!! none !!!\n");
168 printf(" %s\n", list
);
169 list
+= strlen(list
) + 1;
170 } while(*list
!= '\0');
174 static ALenum
checkALErrors(int linenum
)
176 ALenum err
= alGetError();
177 if(err
!= AL_NO_ERROR
)
178 printf("OpenAL Error: %s (0x%x), @ %d\n", alGetString(err
), err
, linenum
);
181 #define checkALErrors() checkALErrors(__LINE__)
183 static ALCenum
checkALCErrors(ALCdevice
*device
, int linenum
)
185 ALCenum err
= alcGetError(device
);
186 if(err
!= ALC_NO_ERROR
)
187 printf("ALC Error: %s (0x%x), @ %d\n", alcGetString(device
, err
), err
, linenum
);
190 #define checkALCErrors(x) checkALCErrors((x),__LINE__)
193 static void printALCInfo(ALCdevice
*device
)
199 const ALCchar
*devname
= NULL
;
201 if(alcIsExtensionPresent(device
, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE
)
202 devname
= alcGetString(device
, ALC_ALL_DEVICES_SPECIFIER
);
203 if(checkALCErrors(device
) != ALC_NO_ERROR
|| !devname
)
204 devname
= alcGetString(device
, ALC_DEVICE_SPECIFIER
);
205 printf("** Info for device \"%s\" **\n", devname
);
207 alcGetIntegerv(device
, ALC_MAJOR_VERSION
, 1, &major
);
208 alcGetIntegerv(device
, ALC_MINOR_VERSION
, 1, &minor
);
209 if(checkALCErrors(device
) == ALC_NO_ERROR
)
210 printf("ALC version: %d.%d\n", major
, minor
);
213 printf("ALC extensions:");
214 printList(alcGetString(device
, ALC_EXTENSIONS
), ' ');
215 checkALCErrors(device
);
219 static void printHRTFInfo(ALCdevice
*device
)
221 LPALCGETSTRINGISOFT alcGetStringiSOFT
;
224 if(alcIsExtensionPresent(device
, "ALC_SOFT_HRTF") == ALC_FALSE
)
226 printf("HRTF extension not available\n");
230 alcGetStringiSOFT
= (LPALCGETSTRINGISOFT
)alcGetProcAddress(device
, "alcGetStringiSOFT");
232 alcGetIntegerv(device
, ALC_NUM_HRTF_SPECIFIERS_SOFT
, 1, &num_hrtfs
);
234 printf("No HRTFs found\n");
238 printf("Available HRTFs:\n");
239 for(i
= 0;i
< num_hrtfs
;++i
)
241 const ALCchar
*name
= alcGetStringiSOFT(device
, ALC_HRTF_SPECIFIER_SOFT
, i
);
242 printf(" %s\n", name
);
245 checkALCErrors(device
);
248 static void printALInfo(void)
250 printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR
));
251 printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER
));
252 printf("OpenAL version string: %s\n", alGetString(AL_VERSION
));
253 printf("OpenAL extensions:");
254 printList(alGetString(AL_EXTENSIONS
), ' ');
258 static void printResamplerInfo(void)
260 LPALGETSTRINGISOFT alGetStringiSOFT
;
261 ALint num_resamplers
;
264 if(!alIsExtensionPresent("AL_SOFT_source_resampler"))
266 printf("Resampler info not available\n");
270 alGetStringiSOFT
= (LPALGETSTRINGISOFT
)alGetProcAddress("alGetStringiSOFT");
272 num_resamplers
= alGetInteger(AL_NUM_RESAMPLERS_SOFT
);
273 def_resampler
= alGetInteger(AL_DEFAULT_RESAMPLER_SOFT
);
276 printf("!!! No resamplers found !!!\n");
280 printf("Available resamplers:\n");
281 for(i
= 0;i
< num_resamplers
;++i
)
283 const ALchar
*name
= alGetStringiSOFT(AL_RESAMPLER_NAME_SOFT
, i
);
284 printf(" %s%s\n", name
, (i
==def_resampler
)?" *":"");
290 static void printEFXInfo(ALCdevice
*device
)
292 ALCint major
, minor
, sends
;
293 static const ALchar filters
[][32] = {
294 "AL_FILTER_LOWPASS", "AL_FILTER_HIGHPASS", "AL_FILTER_BANDPASS", ""
296 char filterNames
[] = "Low-pass,High-pass,Band-pass,";
297 static const ALchar effects
[][32] = {
298 "AL_EFFECT_EAXREVERB", "AL_EFFECT_REVERB", "AL_EFFECT_CHORUS",
299 "AL_EFFECT_DISTORTION", "AL_EFFECT_ECHO", "AL_EFFECT_FLANGER",
300 "AL_EFFECT_FREQUENCY_SHIFTER", "AL_EFFECT_VOCAL_MORPHER",
301 "AL_EFFECT_PITCH_SHIFTER", "AL_EFFECT_RING_MODULATOR",
302 "AL_EFFECT_AUTOWAH", "AL_EFFECT_COMPRESSOR", "AL_EFFECT_EQUALIZER", ""
304 static const ALchar dedeffects
[][64] = {
305 "AL_EFFECT_DEDICATED_DIALOGUE",
306 "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", ""
308 char effectNames
[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger,"
309 "Frequency Shifter,Vocal Morpher,Pitch Shifter,"
310 "Ring Modulator,Autowah,Compressor,Equalizer,"
311 "Dedicated Dialog,Dedicated LFE,";
315 if(alcIsExtensionPresent(device
, "ALC_EXT_EFX") == AL_FALSE
)
317 printf("EFX not available\n");
321 alcGetIntegerv(device
, ALC_EFX_MAJOR_VERSION
, 1, &major
);
322 alcGetIntegerv(device
, ALC_EFX_MINOR_VERSION
, 1, &minor
);
323 if(checkALCErrors(device
) == ALC_NO_ERROR
)
324 printf("EFX version: %d.%d\n", major
, minor
);
325 alcGetIntegerv(device
, ALC_MAX_AUXILIARY_SENDS
, 1, &sends
);
326 if(checkALCErrors(device
) == ALC_NO_ERROR
)
327 printf("Max auxiliary sends: %d\n", sends
);
329 current
= filterNames
;
330 for(i
= 0;filters
[i
][0];i
++)
332 char *next
= strchr(current
, ',');
335 val
= alGetEnumValue(filters
[i
]);
336 if(alGetError() != AL_NO_ERROR
|| val
== 0 || val
== -1)
337 memmove(current
, next
+1, strlen(next
));
341 printf("Supported filters:");
342 printList(filterNames
, ',');
344 current
= effectNames
;
345 for(i
= 0;effects
[i
][0];i
++)
347 char *next
= strchr(current
, ',');
350 val
= alGetEnumValue(effects
[i
]);
351 if(alGetError() != AL_NO_ERROR
|| val
== 0 || val
== -1)
352 memmove(current
, next
+1, strlen(next
));
356 if(alcIsExtensionPresent(device
, "ALC_EXT_DEDICATED"))
358 for(i
= 0;dedeffects
[i
][0];i
++)
360 char *next
= strchr(current
, ',');
363 val
= alGetEnumValue(dedeffects
[i
]);
364 if(alGetError() != AL_NO_ERROR
|| val
== 0 || val
== -1)
365 memmove(current
, next
+1, strlen(next
));
372 for(i
= 0;dedeffects
[i
][0];i
++)
374 char *next
= strchr(current
, ',');
375 memmove(current
, next
+1, strlen(next
));
378 printf("Supported effects:");
379 printList(effectNames
, ',');
382 int main(int argc
, char *argv
[])
387 if(argc
> 1 && (strcmp(argv
[1], "--help") == 0 ||
388 strcmp(argv
[1], "-h") == 0))
390 printf("Usage: %s [playback device]\n", argv
[0]);
394 printf("Available playback devices:\n");
395 if(alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE
)
396 printDeviceList(alcGetString(NULL
, ALC_ALL_DEVICES_SPECIFIER
));
398 printDeviceList(alcGetString(NULL
, ALC_DEVICE_SPECIFIER
));
399 printf("Available capture devices:\n");
400 printDeviceList(alcGetString(NULL
, ALC_CAPTURE_DEVICE_SPECIFIER
));
402 if(alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE
)
403 printf("Default playback device: %s\n",
404 alcGetString(NULL
, ALC_DEFAULT_ALL_DEVICES_SPECIFIER
));
406 printf("Default playback device: %s\n",
407 alcGetString(NULL
, ALC_DEFAULT_DEVICE_SPECIFIER
));
408 printf("Default capture device: %s\n",
409 alcGetString(NULL
, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
));
413 device
= alcOpenDevice((argc
>1) ? argv
[1] : NULL
);
416 printf("\n!!! Failed to open %s !!!\n\n", ((argc
>1) ? argv
[1] : "default device"));
419 printALCInfo(device
);
420 printHRTFInfo(device
);
422 context
= alcCreateContext(device
, NULL
);
423 if(!context
|| alcMakeContextCurrent(context
) == ALC_FALSE
)
426 alcDestroyContext(context
);
427 alcCloseDevice(device
);
428 printf("\n!!! Failed to set a context !!!\n\n");
433 printResamplerInfo();
434 printEFXInfo(device
);
436 alcMakeContextCurrent(NULL
);
437 alcDestroyContext(context
);
438 alcCloseDevice(device
);