test/testaudiohotplug.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 23 Apr 2019 07:59:31 -0700
changeset 12714 9b7633bd0aa0
parent 12503 806492103856
permissions -rw-r--r--
Use _Exit() when available
     1 /*
     2   Copyright (C) 1997-2019 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: */