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