1 /* 2 Copyright (C) 1997-2014 Sam Lantinga <slouken (at) libsdl.org> 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely. 11 */ 12 #include "SDL.h" 13 14 static SDL_AudioSpec spec; 15 static Uint8 *sound = NULL; /* Pointer to wave data */ 16 static Uint32 soundlen = 0; /* Length of wave data */ 17 18 typedef struct 19 { 20 SDL_AudioDeviceID dev; 21 int soundpos; 22 volatile int done; 23 } callback_data; 24 25 void SDLCALL 26 play_through_once(void *arg, Uint8 * stream, int len) 27 { 28 callback_data *cbd = (callback_data *) arg; 29 Uint8 *waveptr = sound + cbd->soundpos; 30 int waveleft = soundlen - cbd->soundpos; 31 int cpy = len; 32 if (cpy > waveleft) 33 cpy = waveleft; 34 35 SDL_memcpy(stream, waveptr, cpy); 36 len -= cpy; 37 cbd->soundpos += cpy; 38 if (len > 0) { 39 stream += cpy; 40 SDL_memset(stream, spec.silence, len); 41 cbd->done++; 42 } 43 } 44 45 static void 46 test_multi_audio(int devcount) 47 { 48 callback_data cbd[64]; 49 int keep_going = 1; 50 int i; 51 52 if (devcount > 64) { 53 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Too many devices (%d), clamping to 64...\n", 54 devcount); 55 devcount = 64; 56 } 57 58 spec.callback = play_through_once; 59 60 for (i = 0; i < devcount; i++) { 61 const char *devname = SDL_GetAudioDeviceName(i, 0); 62 SDL_Log("playing on device #%d: ('%s')...", i, devname); 63 fflush(stdout); 64 65 SDL_memset(&cbd[0], '\0', sizeof(callback_data)); 66 spec.userdata = &cbd[0]; 67 cbd[0].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0); 68 if (cbd[0].dev == 0) { 69 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device failed: %s\n", SDL_GetError()); 70 } else { 71 SDL_PauseAudioDevice(cbd[0].dev, 0); 72 while (!cbd[0].done) 73 SDL_Delay(100); 74 SDL_PauseAudioDevice(cbd[0].dev, 1); 75 SDL_Log("done.\n"); 76 SDL_CloseAudioDevice(cbd[0].dev); 77 } 78 } 79 80 SDL_memset(cbd, '\0', sizeof(cbd)); 81 82 SDL_Log("playing on all devices...\n"); 83 for (i = 0; i < devcount; i++) { 84 const char *devname = SDL_GetAudioDeviceName(i, 0); 85 spec.userdata = &cbd[i]; 86 cbd[i].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0); 87 if (cbd[i].dev == 0) { 88 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device %d failed: %s\n", i, SDL_GetError()); 89 } 90 } 91 92 for (i = 0; i < devcount; i++) { 93 if (cbd[i].dev) { 94 SDL_PauseAudioDevice(cbd[i].dev, 0); 95 } 96 } 97 98 while (keep_going) { 99 keep_going = 0; 100 for (i = 0; i < devcount; i++) { 101 if ((cbd[i].dev) && (!cbd[i].done)) { 102 keep_going = 1; 103 } 104 } 105 SDL_Delay(100); 106 } 107 108 for (i = 0; i < devcount; i++) { 109 if (cbd[i].dev) { 110 SDL_PauseAudioDevice(cbd[i].dev, 1); 111 SDL_CloseAudioDevice(cbd[i].dev); 112 } 113 } 114 115 SDL_Log("All done!\n"); 116 } 117 118 119 int 120 main(int argc, char **argv) 121 { 122 int devcount = 0; 123 124 /* Enable standard application logging */ 125 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 126 127 /* Load the SDL library */ 128 if (SDL_Init(SDL_INIT_AUDIO) < 0) { 129 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); 130 return (1); 131 } 132 133 SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); 134 135 devcount = SDL_GetNumAudioDevices(0); 136 if (devcount < 1) { 137 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio devices!\n"); 138 } else { 139 if (argv[1] == NULL) { 140 argv[1] = "sample.wav"; 141 } 142 143 /* Load the wave file into memory */ 144 if (SDL_LoadWAV(argv[1], &spec, &sound, &soundlen) == NULL) { 145 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", argv[1], 146 SDL_GetError()); 147 } else { 148 test_multi_audio(devcount); 149 SDL_FreeWAV(sound); 150 } 151 } 152 153 SDL_Quit(); 154 return 0; 155 } 156