Atlas - testaudiohotplug.c

Home / ext / SDL / test Lines: 1 | Size: 6273 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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 <SDL3/SDL.h> 16#include <SDL3/SDL_main.h> 17#include <SDL3/SDL_test.h> 18#include "testutils.h" 19 20#ifdef SDL_PLATFORM_EMSCRIPTEN 21#include <emscripten/emscripten.h> 22#endif 23 24#include <stdlib.h> 25 26#ifdef HAVE_SIGNAL_H 27#include <signal.h> 28#endif 29 30static SDL_AudioSpec spec; 31static Uint8 *sound = NULL; /* Pointer to wave data */ 32static Uint32 soundlen = 0; /* Length of wave data */ 33 34static SDLTest_CommonState *state; 35 36/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ 37static void 38quit(int rc) 39{ 40 SDL_Quit(); 41 SDLTest_CommonDestroyState(state); 42 /* Let 'main()' return normally */ 43 if (rc != 0) { 44 exit(rc); 45 } 46} 47 48static int done = 0; 49 50static void poked(int sig) 51{ 52 done = 1; 53} 54 55static const char *devtypestr(int recording) 56{ 57 return recording ? "recording" : "playback"; 58} 59 60static void iteration(void) 61{ 62 SDL_Event e; 63 SDL_AudioDeviceID dev; 64 while (SDL_PollEvent(&e)) { 65 if (e.type == SDL_EVENT_QUIT) { 66 done = 1; 67 } else if (e.type == SDL_EVENT_KEY_UP) { 68 if (e.key.key == SDLK_ESCAPE) { 69 done = 1; 70 } 71 } else if (e.type == SDL_EVENT_AUDIO_DEVICE_ADDED) { 72 const SDL_AudioDeviceID which = e.adevice.which; 73 const bool recording = e.adevice.recording ? true : false; 74 const char *name = SDL_GetAudioDeviceName(which); 75 if (name) { 76 SDL_Log("New %s audio device at id %u: %s", devtypestr(recording), (unsigned int)which, name); 77 } else { 78 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Got new %s device, id %u, but failed to get the name: %s", 79 devtypestr(recording), (unsigned int)which, SDL_GetError()); 80 continue; 81 } 82 if (!recording) { 83 SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(which, &spec, NULL, NULL); 84 if (!stream) { 85 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create/bind an audio stream to %u ('%s'): %s", (unsigned int) which, name, SDL_GetError()); 86 } else { 87 SDL_Log("Opened '%s' as %u", name, (unsigned int) which); 88 /* !!! FIXME: laziness, this used to loop the audio, but we'll just play it once for now on each connect. */ 89 SDL_PutAudioStreamData(stream, sound, soundlen); 90 SDL_FlushAudioStream(stream); 91 SDL_ResumeAudioStreamDevice(stream); 92 /* !!! FIXME: this is leaking the stream for now. We'll wire it up to a dictionary or whatever later. */ 93 } 94 } 95 } else if (e.type == SDL_EVENT_AUDIO_DEVICE_REMOVED) { 96 dev = e.adevice.which; 97 SDL_Log("%s device %u removed.", devtypestr(e.adevice.recording), (unsigned int)dev); 98 /* !!! FIXME: we need to keep track of our streams and destroy them here. */ 99 } 100 } 101} 102 103#ifdef SDL_PLATFORM_EMSCRIPTEN 104static void loop(void) 105{ 106 if (done) 107 emscripten_cancel_main_loop(); 108 else 109 iteration(); 110} 111#endif 112 113int main(int argc, char *argv[]) 114{ 115 int i; 116 char *filename = NULL; 117 SDL_Window *window; 118 119 /* Initialize test framework */ 120 state = SDLTest_CommonCreateState(argv, 0); 121 if (!state) { 122 return 1; 123 } 124 125 /* Parse commandline */ 126 for (i = 1; i < argc;) { 127 int consumed; 128 129 consumed = SDLTest_CommonArg(state, i); 130 if (!consumed) { 131 if (!filename) { 132 filename = argv[i]; 133 consumed = 1; 134 } 135 } 136 if (consumed <= 0) { 137 static const char *options[] = { "[sample.wav]", NULL }; 138 SDLTest_CommonLogUsage(state, argv[0], options); 139 exit(1); 140 } 141 142 i += consumed; 143 } 144 145 /* Load the SDL library */ 146 if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { 147 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", 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 window = SDL_CreateWindow("testaudiohotplug", 640, 480, 0); 153 if (!window) { 154 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateWindow failed: %s", SDL_GetError()); 155 quit(1); 156 } 157 SDL_MinimizeWindow(window); 158 159 filename = GetResourceFilename(filename, "sample.wav"); 160 161 if (!filename) { 162 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", SDL_GetError()); 163 quit(1); 164 } 165 166 /* Load the wave file into memory */ 167 if (!SDL_LoadWAV(filename, &spec, &sound, &soundlen)) { 168 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", filename, SDL_GetError()); 169 quit(1); 170 } 171 172#ifdef HAVE_SIGNAL_H 173 /* Set the signals */ 174#ifdef SIGHUP 175 (void)signal(SIGHUP, poked); 176#endif 177 (void)signal(SIGINT, poked); 178#ifdef SIGQUIT 179 (void)signal(SIGQUIT, poked); 180#endif 181 (void)signal(SIGTERM, poked); 182#endif /* HAVE_SIGNAL_H */ 183 184 /* Show the list of available drivers */ 185 SDL_Log("Available audio drivers:"); 186 for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) { 187 SDL_Log("%i: %s", i, SDL_GetAudioDriver(i)); 188 } 189 190 SDL_Log("Select a driver with the SDL_AUDIO_DRIVER environment variable."); 191 SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver()); 192 193#ifdef SDL_PLATFORM_EMSCRIPTEN 194 emscripten_set_main_loop(loop, 0, 1); 195#else 196 while (!done) { 197 SDL_Delay(100); 198 iteration(); 199 } 200#endif 201 202 /* Clean up on signal */ 203 /* Quit audio first, then free WAV. This prevents access violations in the audio threads. */ 204 SDL_QuitSubSystem(SDL_INIT_AUDIO); 205 SDL_free(sound); 206 SDL_free(filename); 207 quit(0); 208 return 0; 209} 210
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.