SDL_androidaudio.c (5447B)
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 35static SDL_AudioDevice* audioDevice = NULL; 36 37static int 38AndroidAUD_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 97static void 98AndroidAUD_PlayDevice(_THIS) 99{ 100 Android_JNI_WriteAudioBuffer(); 101} 102 103static Uint8 * 104AndroidAUD_GetDeviceBuf(_THIS) 105{ 106 return Android_JNI_GetAudioBuffer(); 107} 108 109static void 110AndroidAUD_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 126static int 127AndroidAUD_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 143AudioBootStrap 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 */ 148void 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 */ 167void 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