testaudiohotplug.c (5579B)
1 /* 2 Copyright (C) 1997-2020 Sam Lantinga <slouken@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 13 /* Program to test hotplugging of audio devices */ 14 15 #include "SDL_config.h" 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 20 #if HAVE_SIGNAL_H 21 #include <signal.h> 22 #endif 23 24 #ifdef __EMSCRIPTEN__ 25 #include <emscripten/emscripten.h> 26 #endif 27 28 #include "SDL.h" 29 30 static SDL_AudioSpec spec; 31 static Uint8 *sound = NULL; /* Pointer to wave data */ 32 static Uint32 soundlen = 0; /* Length of wave data */ 33 34 static int posindex = 0; 35 static Uint32 positions[64]; 36 37 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ 38 static void 39 quit(int rc) 40 { 41 SDL_Quit(); 42 exit(rc); 43 } 44 45 void SDLCALL 46 fillerup(void *_pos, Uint8 * stream, int len) 47 { 48 Uint32 pos = *((Uint32 *) _pos); 49 Uint8 *waveptr; 50 int waveleft; 51 52 /* Set up the pointers */ 53 waveptr = sound + pos; 54 waveleft = soundlen - pos; 55 56 /* Go! */ 57 while (waveleft <= len) { 58 SDL_memcpy(stream, waveptr, waveleft); 59 stream += waveleft; 60 len -= waveleft; 61 waveptr = sound; 62 waveleft = soundlen; 63 pos = 0; 64 } 65 SDL_memcpy(stream, waveptr, len); 66 pos += len; 67 *((Uint32 *) _pos) = pos; 68 } 69 70 static int done = 0; 71 void 72 poked(int sig) 73 { 74 done = 1; 75 } 76 77 static const char* 78 devtypestr(int iscapture) 79 { 80 return iscapture ? "capture" : "output"; 81 } 82 83 static void 84 iteration() 85 { 86 SDL_Event e; 87 SDL_AudioDeviceID dev; 88 while (SDL_PollEvent(&e)) { 89 if (e.type == SDL_QUIT) { 90 done = 1; 91 } else if (e.type == SDL_KEYUP) { 92 if (e.key.keysym.sym == SDLK_ESCAPE) 93 done = 1; 94 } else if (e.type == SDL_AUDIODEVICEADDED) { 95 int index = e.adevice.which; 96 int iscapture = e.adevice.iscapture; 97 const char *name = SDL_GetAudioDeviceName(index, iscapture); 98 if (name != NULL) 99 SDL_Log("New %s audio device at index %u: %s\n", devtypestr(iscapture), (unsigned int) index, name); 100 else { 101 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Got new %s device at index %u, but failed to get the name: %s\n", 102 devtypestr(iscapture), (unsigned int) index, SDL_GetError()); 103 continue; 104 } 105 if (!iscapture) { 106 positions[posindex] = 0; 107 spec.userdata = &positions[posindex++]; 108 spec.callback = fillerup; 109 dev = SDL_OpenAudioDevice(name, 0, &spec, NULL, 0); 110 if (!dev) { 111 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open '%s': %s\n", name, SDL_GetError()); 112 } else { 113 SDL_Log("Opened '%s' as %u\n", name, (unsigned int) dev); 114 SDL_PauseAudioDevice(dev, 0); 115 } 116 } 117 } else if (e.type == SDL_AUDIODEVICEREMOVED) { 118 dev = (SDL_AudioDeviceID) e.adevice.which; 119 SDL_Log("%s device %u removed.\n", devtypestr(e.adevice.iscapture), (unsigned int) dev); 120 SDL_CloseAudioDevice(dev); 121 } 122 } 123 } 124 125 #ifdef __EMSCRIPTEN__ 126 void 127 loop() 128 { 129 if(done) 130 emscripten_cancel_main_loop(); 131 else 132 iteration(); 133 } 134 #endif 135 136 int 137 main(int argc, char *argv[]) 138 { 139 int i; 140 char filename[4096]; 141 142 /* Enable standard application logging */ 143 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 144 145 /* Load the SDL library */ 146 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { 147 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); 148 return (1); 149 } 150 151 /* Some targets (Mac CoreAudio) need an event queue for audio hotplug, so make and immediately hide a window. */ 152 SDL_MinimizeWindow(SDL_CreateWindow("testaudiohotplug", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0)); 153 154 if (argc > 1) { 155 SDL_strlcpy(filename, argv[1], sizeof(filename)); 156 } else { 157 SDL_strlcpy(filename, "sample.wav", sizeof(filename)); 158 } 159 /* Load the wave file into memory */ 160 if (SDL_LoadWAV(filename, &spec, &sound, &soundlen) == NULL) { 161 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError()); 162 quit(1); 163 } 164 165 #if HAVE_SIGNAL_H 166 /* Set the signals */ 167 #ifdef SIGHUP 168 signal(SIGHUP, poked); 169 #endif 170 signal(SIGINT, poked); 171 #ifdef SIGQUIT 172 signal(SIGQUIT, poked); 173 #endif 174 signal(SIGTERM, poked); 175 #endif /* HAVE_SIGNAL_H */ 176 177 /* Show the list of available drivers */ 178 SDL_Log("Available audio drivers:"); 179 for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) { 180 SDL_Log("%i: %s", i, SDL_GetAudioDriver(i)); 181 } 182 183 SDL_Log("Select a driver with the SDL_AUDIODRIVER environment variable.\n"); 184 SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); 185 186 #ifdef __EMSCRIPTEN__ 187 emscripten_set_main_loop(loop, 0, 1); 188 #else 189 while (!done) { 190 SDL_Delay(100); 191 iteration(); 192 } 193 #endif 194 195 /* Clean up on signal */ 196 /* Quit audio first, then free WAV. This prevents access violations in the audio threads. */ 197 SDL_QuitSubSystem(SDL_INIT_AUDIO); 198 SDL_FreeWAV(sound); 199 SDL_Quit(); 200 return (0); 201 } 202 203 /* vi: set ts=4 sw=4 expandtab: */