src/audio/android/SDL_androidaudio.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Wed, 29 Oct 2014 20:20:47 +0100
changeset 9201 21d9f9babb30
parent 9148 e9b6e9f4a10e
child 9394 bb28e5281770
permissions -rw-r--r--
Fixed bug 2647 - Memory leak in SDL_AddHintCallback function - SDL_hints.c

Nitz

Variable entry going out of scope leaks the storage it points to, at:

/* Need to add a hint entry for this watcher */
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
if (!hint) {
return;
}

Patch is attached.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 #if SDL_AUDIO_DRIVER_ANDROID
    24 
    25 /* Output audio to Android */
    26 
    27 #include "SDL_audio.h"
    28 #include "../SDL_audio_c.h"
    29 #include "SDL_androidaudio.h"
    30 
    31 #include "../../core/android/SDL_android.h"
    32 
    33 #include <android/log.h>
    34 
    35 static SDL_AudioDevice* audioDevice = NULL;
    36 
    37 static int
    38 AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
    39 {
    40     SDL_AudioFormat test_format;
    41 
    42     if (iscapture) {
    43         /* TODO: implement capture */
    44         return SDL_SetError("Capture not supported on Android");
    45     }
    46 
    47     if (audioDevice != NULL) {
    48         return SDL_SetError("Only one audio device at a time please!");
    49     }
    50 
    51     audioDevice = this;
    52     
    53     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
    54     if (this->hidden == NULL) {
    55         return SDL_OutOfMemory();
    56     }
    57 
    58     test_format = SDL_FirstAudioFormat(this->spec.format);
    59     while (test_format != 0) { /* no "UNKNOWN" constant */
    60         if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
    61             this->spec.format = test_format;
    62             break;
    63         }
    64         test_format = SDL_NextAudioFormat();
    65     }
    66 
    67     if (test_format == 0) {
    68         /* Didn't find a compatible format :( */
    69         return SDL_SetError("No compatible audio format!");
    70     }
    71 
    72     if (this->spec.channels > 1) {
    73         this->spec.channels = 2;
    74     } else {
    75         this->spec.channels = 1;
    76     }
    77 
    78     if (this->spec.freq < 8000) {
    79         this->spec.freq = 8000;
    80     }
    81     if (this->spec.freq > 48000) {
    82         this->spec.freq = 48000;
    83     }
    84 
    85     /* TODO: pass in/return a (Java) device ID, also whether we're opening for input or output */
    86     this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
    87     SDL_CalculateAudioSpec(&this->spec);
    88 
    89     if (this->spec.samples == 0) {
    90         /* Init failed? */
    91         return SDL_SetError("Java-side initialization failed!");
    92     }
    93 
    94     return 0;
    95 }
    96 
    97 static void
    98 AndroidAUD_PlayDevice(_THIS)
    99 {
   100     Android_JNI_WriteAudioBuffer();
   101 }
   102 
   103 static Uint8 *
   104 AndroidAUD_GetDeviceBuf(_THIS)
   105 {
   106     return Android_JNI_GetAudioBuffer();
   107 }
   108 
   109 static void
   110 AndroidAUD_CloseDevice(_THIS)
   111 {
   112     /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
   113        so it's safe to terminate the Java side buffer and AudioTrack
   114      */
   115     Android_JNI_CloseAudioDevice();
   116 
   117     if (audioDevice == this) {
   118         if (audioDevice->hidden != NULL) {
   119             SDL_free(this->hidden);
   120             this->hidden = NULL;
   121         }
   122         audioDevice = NULL;
   123     }
   124 }
   125 
   126 static int
   127 AndroidAUD_Init(SDL_AudioDriverImpl * impl)
   128 {
   129     /* Set the function pointers */
   130     impl->OpenDevice = AndroidAUD_OpenDevice;
   131     impl->PlayDevice = AndroidAUD_PlayDevice;
   132     impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf;
   133     impl->CloseDevice = AndroidAUD_CloseDevice;
   134 
   135     /* and the capabilities */
   136     impl->HasCaptureSupport = 0; /* TODO */
   137     impl->OnlyHasDefaultOutputDevice = 1;
   138     impl->OnlyHasDefaultInputDevice = 1;
   139 
   140     return 1;   /* this audio target is available. */
   141 }
   142 
   143 AudioBootStrap ANDROIDAUD_bootstrap = {
   144     "android", "SDL Android audio driver", AndroidAUD_Init, 0
   145 };
   146 
   147 /* Pause (block) all non already paused audio devices by taking their mixer lock */
   148 void AndroidAUD_PauseDevices(void)
   149 {
   150     /* TODO: Handle multiple devices? */
   151     struct SDL_PrivateAudioData *private;
   152     if(audioDevice != NULL && audioDevice->hidden != NULL) {
   153         private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
   154         if (audioDevice->paused) {
   155             /* The device is already paused, leave it alone */
   156             private->resume = SDL_FALSE;
   157         }
   158         else {
   159             SDL_LockMutex(audioDevice->mixer_lock);
   160             audioDevice->paused = SDL_TRUE;
   161             private->resume = SDL_TRUE;
   162         }
   163     }
   164 }
   165 
   166 /* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
   167 void AndroidAUD_ResumeDevices(void)
   168 {
   169     /* TODO: Handle multiple devices? */
   170     struct SDL_PrivateAudioData *private;
   171     if(audioDevice != NULL && audioDevice->hidden != NULL) {
   172         private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
   173         if (private->resume) {
   174             audioDevice->paused = SDL_FALSE;
   175             private->resume = SDL_FALSE;
   176             SDL_UnlockMutex(audioDevice->mixer_lock);
   177         }
   178     }
   179 }
   180 
   181 
   182 #endif /* SDL_AUDIO_DRIVER_ANDROID */
   183 
   184 /* vi: set ts=4 sw=4 expandtab: */
   185