test/testaudiohotplug.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:09 -0800
changeset 11730 ac6c607e065c
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Enable building the Metal renderer by default, and weak link the Metal framework so the SDL library is safe to use on older Macs
Also generate iOS versions of the Metal shaders
     1 /*
     2   Copyright (C) 1997-2017 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: */