#include "SDL.h"
#include <stdio.h>
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
#include "testutils.h"
static SDL_AudioSpec spec;
static Uint8 *sound = NULL;
static Uint32 soundlen = 0;
typedef struct
{
SDL_AudioDeviceID dev;
int soundpos;
SDL_atomic_t done;
} callback_data;
callback_data cbd[64];
void SDLCALL
play_through_once(void *arg, Uint8 * stream, int len)
{
callback_data *cbdata = (callback_data *) arg;
Uint8 *waveptr = sound + cbdata->soundpos;
int waveleft = soundlen - cbdata->soundpos;
int cpy = len;
if (cpy > waveleft)
cpy = waveleft;
SDL_memcpy(stream, waveptr, cpy);
len -= cpy;
cbdata->soundpos += cpy;
if (len > 0) {
stream += cpy;
SDL_memset(stream, spec.silence, len);
SDL_AtomicSet(&cbdata->done, 1);
}
}
void
loop()
{
if (SDL_AtomicGet(&cbd[0].done)) {
#ifdef __EMSCRIPTEN__
emscripten_cancel_main_loop();
#endif
SDL_PauseAudioDevice(cbd[0].dev, 1);
SDL_CloseAudioDevice(cbd[0].dev);
SDL_FreeWAV(sound);
SDL_Quit();
}
}
static void
test_multi_audio(int devcount)
{
int keep_going = 1;
int i;
#ifdef __ANDROID__
SDL_Event event;
SDL_CreateWindow("testmultiaudio", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0);
#endif
if (devcount > 64) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Too many devices (%d), clamping to 64...\n",
devcount);
devcount = 64;
}
spec.callback = play_through_once;
for (i = 0; i < devcount; i++) {
const char *devname = SDL_GetAudioDeviceName(i, 0);
SDL_Log("playing on device #%d: ('%s')...", i, devname);
fflush(stdout);
SDL_memset(&cbd[0], '\0', sizeof(callback_data));
spec.userdata = &cbd[0];
cbd[0].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0);
if (cbd[0].dev == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device failed: %s\n", SDL_GetError());
} else {
SDL_PauseAudioDevice(cbd[0].dev, 0);
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(loop, 0, 1);
#else
while (!SDL_AtomicGet(&cbd[0].done)) {
#ifdef __ANDROID__
while (SDL_PollEvent(&event)){}
#endif
SDL_Delay(100);
}
SDL_PauseAudioDevice(cbd[0].dev, 1);
#endif
SDL_Log("done.\n");
SDL_CloseAudioDevice(cbd[0].dev);
}
}
SDL_memset(cbd, '\0', sizeof(cbd));
SDL_Log("playing on all devices...\n");
for (i = 0; i < devcount; i++) {
const char *devname = SDL_GetAudioDeviceName(i, 0);
spec.userdata = &cbd[i];
cbd[i].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0);
if (cbd[i].dev == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device %d failed: %s\n", i, SDL_GetError());
}
}
for (i = 0; i < devcount; i++) {
if (cbd[i].dev) {
SDL_PauseAudioDevice(cbd[i].dev, 0);
}
}
while (keep_going) {
keep_going = 0;
for (i = 0; i < devcount; i++) {
if ((cbd[i].dev) && (!SDL_AtomicGet(&cbd[i].done))) {
keep_going = 1;
}
}
#ifdef __ANDROID__
while (SDL_PollEvent(&event)){}
#endif
SDL_Delay(100);
}
#ifndef __EMSCRIPTEN__
for (i = 0; i < devcount; i++) {
if (cbd[i].dev) {
SDL_PauseAudioDevice(cbd[i].dev, 1);
SDL_CloseAudioDevice(cbd[i].dev);
}
}
SDL_Log("All done!\n");
#endif
}
int
main(int argc, char **argv)
{
int devcount = 0;
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
return (1);
}
SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
devcount = SDL_GetNumAudioDevices(0);
if (devcount < 1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio devices!\n");
} else {
char *file = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav");
if (SDL_LoadWAV(file, &spec, &sound, &soundlen) == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", file,
SDL_GetError());
} else {
test_multi_audio(devcount);
SDL_FreeWAV(sound);
}
SDL_free(file);
}
SDL_Quit();
return 0;
}