SDL_androidaudio.c (6269B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2020 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 static SDL_AudioDevice* captureDevice = NULL; 37 38 static int 39 ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) 40 { 41 SDL_AudioFormat test_format; 42 43 SDL_assert((captureDevice == NULL) || !iscapture); 44 SDL_assert((audioDevice == NULL) || iscapture); 45 46 if (iscapture) { 47 captureDevice = this; 48 } else { 49 audioDevice = this; 50 } 51 52 this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden)); 53 if (this->hidden == NULL) { 54 return SDL_OutOfMemory(); 55 } 56 57 test_format = SDL_FirstAudioFormat(this->spec.format); 58 while (test_format != 0) { /* no "UNKNOWN" constant */ 59 if ((test_format == AUDIO_U8) || 60 (test_format == AUDIO_S16) || 61 (test_format == AUDIO_F32)) { 62 this->spec.format = test_format; 63 break; 64 } 65 test_format = SDL_NextAudioFormat(); 66 } 67 68 if (test_format == 0) { 69 /* Didn't find a compatible format :( */ 70 return SDL_SetError("No compatible audio format!"); 71 } 72 73 if (Android_JNI_OpenAudioDevice(iscapture, &this->spec) < 0) { 74 return -1; 75 } 76 77 SDL_CalculateAudioSpec(&this->spec); 78 79 return 0; 80 } 81 82 static void 83 ANDROIDAUDIO_PlayDevice(_THIS) 84 { 85 Android_JNI_WriteAudioBuffer(); 86 } 87 88 static Uint8 * 89 ANDROIDAUDIO_GetDeviceBuf(_THIS) 90 { 91 return Android_JNI_GetAudioBuffer(); 92 } 93 94 static int 95 ANDROIDAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen) 96 { 97 return Android_JNI_CaptureAudioBuffer(buffer, buflen); 98 } 99 100 static void 101 ANDROIDAUDIO_FlushCapture(_THIS) 102 { 103 Android_JNI_FlushCapturedAudio(); 104 } 105 106 static void 107 ANDROIDAUDIO_CloseDevice(_THIS) 108 { 109 /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread 110 so it's safe to terminate the Java side buffer and AudioTrack 111 */ 112 Android_JNI_CloseAudioDevice(this->iscapture); 113 if (this->iscapture) { 114 SDL_assert(captureDevice == this); 115 captureDevice = NULL; 116 } else { 117 SDL_assert(audioDevice == this); 118 audioDevice = NULL; 119 } 120 SDL_free(this->hidden); 121 } 122 123 static int 124 ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl) 125 { 126 /* Set the function pointers */ 127 impl->OpenDevice = ANDROIDAUDIO_OpenDevice; 128 impl->PlayDevice = ANDROIDAUDIO_PlayDevice; 129 impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf; 130 impl->CloseDevice = ANDROIDAUDIO_CloseDevice; 131 impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice; 132 impl->FlushCapture = ANDROIDAUDIO_FlushCapture; 133 134 /* and the capabilities */ 135 impl->HasCaptureSupport = SDL_TRUE; 136 impl->OnlyHasDefaultOutputDevice = 1; 137 impl->OnlyHasDefaultCaptureDevice = 1; 138 139 return 1; /* this audio target is available. */ 140 } 141 142 AudioBootStrap ANDROIDAUDIO_bootstrap = { 143 "android", "SDL Android audio driver", ANDROIDAUDIO_Init, 0 144 }; 145 146 /* Pause (block) all non already paused audio devices by taking their mixer lock */ 147 void ANDROIDAUDIO_PauseDevices(void) 148 { 149 /* TODO: Handle multiple devices? */ 150 struct SDL_PrivateAudioData *private; 151 if(audioDevice != NULL && audioDevice->hidden != NULL) { 152 private = (struct SDL_PrivateAudioData *) audioDevice->hidden; 153 if (SDL_AtomicGet(&audioDevice->paused)) { 154 /* The device is already paused, leave it alone */ 155 private->resume = SDL_FALSE; 156 } 157 else { 158 SDL_LockMutex(audioDevice->mixer_lock); 159 SDL_AtomicSet(&audioDevice->paused, 1); 160 private->resume = SDL_TRUE; 161 } 162 } 163 164 if(captureDevice != NULL && captureDevice->hidden != NULL) { 165 private = (struct SDL_PrivateAudioData *) captureDevice->hidden; 166 if (SDL_AtomicGet(&captureDevice->paused)) { 167 /* The device is already paused, leave it alone */ 168 private->resume = SDL_FALSE; 169 } 170 else { 171 SDL_LockMutex(captureDevice->mixer_lock); 172 SDL_AtomicSet(&captureDevice->paused, 1); 173 private->resume = SDL_TRUE; 174 } 175 } 176 } 177 178 /* Resume (unblock) all non already paused audio devices by releasing their mixer lock */ 179 void ANDROIDAUDIO_ResumeDevices(void) 180 { 181 /* TODO: Handle multiple devices? */ 182 struct SDL_PrivateAudioData *private; 183 if(audioDevice != NULL && audioDevice->hidden != NULL) { 184 private = (struct SDL_PrivateAudioData *) audioDevice->hidden; 185 if (private->resume) { 186 SDL_AtomicSet(&audioDevice->paused, 0); 187 private->resume = SDL_FALSE; 188 SDL_UnlockMutex(audioDevice->mixer_lock); 189 } 190 } 191 192 if(captureDevice != NULL && captureDevice->hidden != NULL) { 193 private = (struct SDL_PrivateAudioData *) captureDevice->hidden; 194 if (private->resume) { 195 SDL_AtomicSet(&captureDevice->paused, 0); 196 private->resume = SDL_FALSE; 197 SDL_UnlockMutex(captureDevice->mixer_lock); 198 } 199 } 200 } 201 202 #else 203 204 void ANDROIDAUDIO_ResumeDevices(void) {} 205 void ANDROIDAUDIO_PauseDevices(void) {} 206 207 #endif /* SDL_AUDIO_DRIVER_ANDROID */ 208 209 /* vi: set ts=4 sw=4 expandtab: */ 210