test/testmultiaudio.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 #include "SDL.h"
    13 
    14 #include <stdio.h> /* for fflush() and stdout */
    15 
    16 #ifdef __EMSCRIPTEN__
    17 #include <emscripten/emscripten.h>
    18 #endif
    19 
    20 static SDL_AudioSpec spec;
    21 static Uint8 *sound = NULL;     /* Pointer to wave data */
    22 static Uint32 soundlen = 0;     /* Length of wave data */
    23 
    24 typedef struct
    25 {
    26     SDL_AudioDeviceID dev;
    27     int soundpos;
    28     SDL_atomic_t done;
    29 } callback_data;
    30 
    31 callback_data cbd[64];
    32 
    33 void SDLCALL
    34 play_through_once(void *arg, Uint8 * stream, int len)
    35 {
    36     callback_data *cbd = (callback_data *) arg;
    37     Uint8 *waveptr = sound + cbd->soundpos;
    38     int waveleft = soundlen - cbd->soundpos;
    39     int cpy = len;
    40     if (cpy > waveleft)
    41         cpy = waveleft;
    42 
    43     SDL_memcpy(stream, waveptr, cpy);
    44     len -= cpy;
    45     cbd->soundpos += cpy;
    46     if (len > 0) {
    47         stream += cpy;
    48         SDL_memset(stream, spec.silence, len);
    49         SDL_AtomicSet(&cbd->done, 1);
    50     }
    51 }
    52 
    53 void
    54 loop()
    55 {
    56     if (SDL_AtomicGet(&cbd[0].done)) {
    57 #ifdef __EMSCRIPTEN__
    58         emscripten_cancel_main_loop();
    59 #endif
    60         SDL_PauseAudioDevice(cbd[0].dev, 1);
    61         SDL_CloseAudioDevice(cbd[0].dev);
    62         SDL_FreeWAV(sound);
    63         SDL_Quit();
    64     }
    65 }
    66 
    67 static void
    68 test_multi_audio(int devcount)
    69 {
    70     int keep_going = 1;
    71     int i;
    72     
    73 #ifdef __ANDROID__  
    74     SDL_Event event;
    75   
    76     /* Create a Window to get fully initialized event processing for testing pause on Android. */
    77     SDL_CreateWindow("testmultiaudio", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0);
    78 #endif
    79 
    80     if (devcount > 64) {
    81         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Too many devices (%d), clamping to 64...\n",
    82                 devcount);
    83         devcount = 64;
    84     }
    85 
    86     spec.callback = play_through_once;
    87 
    88     for (i = 0; i < devcount; i++) {
    89         const char *devname = SDL_GetAudioDeviceName(i, 0);
    90         SDL_Log("playing on device #%d: ('%s')...", i, devname);
    91         fflush(stdout);
    92 
    93         SDL_memset(&cbd[0], '\0', sizeof(callback_data));
    94         spec.userdata = &cbd[0];
    95         cbd[0].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0);
    96         if (cbd[0].dev == 0) {
    97             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device failed: %s\n", SDL_GetError());
    98         } else {
    99             SDL_PauseAudioDevice(cbd[0].dev, 0);
   100 #ifdef __EMSCRIPTEN__
   101             emscripten_set_main_loop(loop, 0, 1);
   102 #else
   103             while (!SDL_AtomicGet(&cbd[0].done)) {
   104                 #ifdef __ANDROID__                
   105                 /* Empty queue, some application events would prevent pause. */
   106                 while (SDL_PollEvent(&event)){}
   107                 #endif                
   108                 SDL_Delay(100);
   109             }
   110             SDL_PauseAudioDevice(cbd[0].dev, 1);
   111 #endif
   112             SDL_Log("done.\n");
   113             SDL_CloseAudioDevice(cbd[0].dev);
   114         }
   115     }
   116 
   117     SDL_memset(cbd, '\0', sizeof(cbd));
   118 
   119     SDL_Log("playing on all devices...\n");
   120     for (i = 0; i < devcount; i++) {
   121         const char *devname = SDL_GetAudioDeviceName(i, 0);
   122         spec.userdata = &cbd[i];
   123         cbd[i].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0);
   124         if (cbd[i].dev == 0) {
   125             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device %d failed: %s\n", i, SDL_GetError());
   126         }
   127     }
   128 
   129     for (i = 0; i < devcount; i++) {
   130         if (cbd[i].dev) {
   131             SDL_PauseAudioDevice(cbd[i].dev, 0);
   132         }
   133     }
   134 
   135     while (keep_going) {
   136         keep_going = 0;
   137         for (i = 0; i < devcount; i++) {
   138             if ((cbd[i].dev) && (!SDL_AtomicGet(&cbd[i].done))) {
   139                 keep_going = 1;
   140             }
   141         }
   142         #ifdef __ANDROID__        
   143         /* Empty queue, some application events would prevent pause. */
   144         while (SDL_PollEvent(&event)){}
   145         #endif        
   146 
   147         SDL_Delay(100);
   148     }
   149 
   150 #ifndef __EMSCRIPTEN__
   151     for (i = 0; i < devcount; i++) {
   152         if (cbd[i].dev) {
   153             SDL_PauseAudioDevice(cbd[i].dev, 1);
   154             SDL_CloseAudioDevice(cbd[i].dev);
   155         }
   156     }
   157 
   158     SDL_Log("All done!\n");
   159 #endif
   160 }
   161 
   162 
   163 int
   164 main(int argc, char **argv)
   165 {
   166     int devcount = 0;
   167 
   168     /* Enable standard application logging */
   169     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   170 
   171     /* Load the SDL library */
   172     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
   173         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
   174         return (1);
   175     }
   176 
   177     SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
   178     
   179     devcount = SDL_GetNumAudioDevices(0);
   180     if (devcount < 1) {
   181         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio devices!\n");
   182     } else {
   183         if (argv[1] == NULL) {
   184             argv[1] = "sample.wav";
   185         }
   186 
   187         /* Load the wave file into memory */
   188         if (SDL_LoadWAV(argv[1], &spec, &sound, &soundlen) == NULL) {
   189             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", argv[1],
   190                     SDL_GetError());
   191         } else {
   192             test_multi_audio(devcount);
   193             SDL_FreeWAV(sound);
   194         }
   195     }
   196 
   197     SDL_Quit();
   198     return 0;
   199 }