test/testmultiaudio.c
author Gabriel Jacobo <gabomdq@gmail.com>
Wed, 17 Sep 2014 11:41:12 -0300
changeset 9145 aa99e029b12e
parent 8851 a7cfe554d337
child 9269 d51f84c20b10
permissions -rw-r--r--
[Android] Fixes #2480, music does not pause when process backgrounded

This modifies SDL_PauseAudio behavior to pause all audio devices instead of
just the default one (required on Android, at least for testmultiaudio on my
Nexus 4 which reported 2 audio devices).
It also changes SDL_PauseAudioDevice to retain the device lock from pause until
resume in order to save battery in mobile devices.
     1 /*
     2   Copyright (C) 1997-2014 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 static SDL_AudioSpec spec;
    17 static Uint8 *sound = NULL;     /* Pointer to wave data */
    18 static Uint32 soundlen = 0;     /* Length of wave data */
    19 
    20 typedef struct
    21 {
    22     SDL_AudioDeviceID dev;
    23     int soundpos;
    24     volatile int done;
    25 } callback_data;
    26 
    27 void SDLCALL
    28 play_through_once(void *arg, Uint8 * stream, int len)
    29 {
    30     callback_data *cbd = (callback_data *) arg;
    31     Uint8 *waveptr = sound + cbd->soundpos;
    32     int waveleft = soundlen - cbd->soundpos;
    33     int cpy = len;
    34     if (cpy > waveleft)
    35         cpy = waveleft;
    36 
    37     SDL_memcpy(stream, waveptr, cpy);
    38     len -= cpy;
    39     cbd->soundpos += cpy;
    40     if (len > 0) {
    41         stream += cpy;
    42         SDL_memset(stream, spec.silence, len);
    43         cbd->done++;
    44     }
    45 }
    46 
    47 static void
    48 test_multi_audio(int devcount)
    49 {
    50     callback_data cbd[64];
    51     int keep_going = 1;
    52     int i;
    53     
    54 #ifdef __ANDROID__  
    55     SDL_Event event;
    56   
    57     SDL_CreateWindow("testmultiaudio", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0);
    58 #endif
    59 
    60     if (devcount > 64) {
    61         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Too many devices (%d), clamping to 64...\n",
    62                 devcount);
    63         devcount = 64;
    64     }
    65 
    66     spec.callback = play_through_once;
    67 
    68     for (i = 0; i < devcount; i++) {
    69         const char *devname = SDL_GetAudioDeviceName(i, 0);
    70         SDL_Log("playing on device #%d: ('%s')...", i, devname);
    71         fflush(stdout);
    72 
    73         SDL_memset(&cbd[0], '\0', sizeof(callback_data));
    74         spec.userdata = &cbd[0];
    75         cbd[0].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0);
    76         if (cbd[0].dev == 0) {
    77             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device failed: %s\n", SDL_GetError());
    78         } else {
    79             SDL_PauseAudioDevice(cbd[0].dev, 0);
    80             while (!cbd[0].done) {
    81 #ifdef __ANDROID__                
    82                 while (SDL_PollEvent(&event)){}
    83 #endif                
    84                 SDL_Delay(100);
    85             }
    86             SDL_PauseAudioDevice(cbd[0].dev, 1);
    87             SDL_Log("done.\n");
    88             SDL_CloseAudioDevice(cbd[0].dev);
    89         }
    90     }
    91 
    92     SDL_memset(cbd, '\0', sizeof(cbd));
    93 
    94     SDL_Log("playing on all devices...\n");
    95     for (i = 0; i < devcount; i++) {
    96         const char *devname = SDL_GetAudioDeviceName(i, 0);
    97         spec.userdata = &cbd[i];
    98         cbd[i].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL, 0);
    99         if (cbd[i].dev == 0) {
   100             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Open device %d failed: %s\n", i, SDL_GetError());
   101         }
   102     }
   103 
   104     for (i = 0; i < devcount; i++) {
   105         if (cbd[i].dev) {
   106             SDL_PauseAudioDevice(cbd[i].dev, 0);
   107         }
   108     }
   109 
   110     while (keep_going) {
   111         keep_going = 0;
   112         for (i = 0; i < devcount; i++) {
   113             if ((cbd[i].dev) && (!cbd[i].done)) {
   114                 keep_going = 1;
   115             }
   116         }
   117 #ifdef __ANDROID__        
   118         while (SDL_PollEvent(&event)){}
   119 #endif        
   120         SDL_Delay(100);
   121     }
   122 
   123     for (i = 0; i < devcount; i++) {
   124         if (cbd[i].dev) {
   125             SDL_PauseAudioDevice(cbd[i].dev, 1);
   126             SDL_CloseAudioDevice(cbd[i].dev);
   127         }
   128     }
   129 
   130     SDL_Log("All done!\n");
   131 }
   132 
   133 
   134 int
   135 main(int argc, char **argv)
   136 {
   137     int devcount = 0;
   138 
   139 	/* Enable standard application logging */
   140     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   141 
   142     /* Load the SDL library */
   143     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
   144         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
   145         return (1);
   146     }
   147 
   148     SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
   149     
   150     devcount = SDL_GetNumAudioDevices(0);
   151     if (devcount < 1) {
   152         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio devices!\n");
   153     } else {
   154         if (argv[1] == NULL) {
   155             argv[1] = "sample.wav";
   156         }
   157 
   158         /* Load the wave file into memory */
   159         if (SDL_LoadWAV(argv[1], &spec, &sound, &soundlen) == NULL) {
   160             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", argv[1],
   161                     SDL_GetError());
   162         } else {
   163             test_multi_audio(devcount);
   164             SDL_FreeWAV(sound);
   165         }
   166     }
   167 
   168     SDL_Quit();
   169     return 0;
   170 }