SDL  2.0
SDL_androidaudio.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 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_assert.h"
28 #include "SDL_audio.h"
29 #include "../SDL_audio_c.h"
30 #include "SDL_androidaudio.h"
31 
32 #include "../../core/android/SDL_android.h"
33 
34 #include <android/log.h>
35 
36 static SDL_AudioDevice* audioDevice = NULL;
37 static SDL_AudioDevice* captureDevice = NULL;
38 
39 static int
40 ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
41 {
42  SDL_AudioFormat test_format;
43 
44  SDL_assert((captureDevice == NULL) || !iscapture);
45  SDL_assert((audioDevice == NULL) || iscapture);
46 
47  if (iscapture) {
48  captureDevice = this;
49  } else {
50  audioDevice = this;
51  }
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) ||
61  (test_format == AUDIO_S16) ||
62  (test_format == AUDIO_F32)) {
63  this->spec.format = test_format;
64  break;
65  }
66  test_format = SDL_NextAudioFormat();
67  }
68 
69  if (test_format == 0) {
70  /* Didn't find a compatible format :( */
71  return SDL_SetError("No compatible audio format!");
72  }
73 
74  if (Android_JNI_OpenAudioDevice(iscapture, &this->spec) < 0) {
75  return -1;
76  }
77 
79 
80  return 0;
81 }
82 
83 static void
84 ANDROIDAUDIO_PlayDevice(_THIS)
85 {
87 }
88 
89 static Uint8 *
90 ANDROIDAUDIO_GetDeviceBuf(_THIS)
91 {
93 }
94 
95 static int
96 ANDROIDAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
97 {
98  return Android_JNI_CaptureAudioBuffer(buffer, buflen);
99 }
100 
101 static void
102 ANDROIDAUDIO_FlushCapture(_THIS)
103 {
105 }
106 
107 static void
108 ANDROIDAUDIO_CloseDevice(_THIS)
109 {
110  /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
111  so it's safe to terminate the Java side buffer and AudioTrack
112  */
113  Android_JNI_CloseAudioDevice(this->iscapture);
114  if (this->iscapture) {
115  SDL_assert(captureDevice == this);
116  captureDevice = NULL;
117  } else {
118  SDL_assert(audioDevice == this);
119  audioDevice = NULL;
120  }
121  SDL_free(this->hidden);
122 }
123 
124 static int
125 ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl)
126 {
127  /* Set the function pointers */
128  impl->OpenDevice = ANDROIDAUDIO_OpenDevice;
129  impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
130  impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
131  impl->CloseDevice = ANDROIDAUDIO_CloseDevice;
132  impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice;
133  impl->FlushCapture = ANDROIDAUDIO_FlushCapture;
134 
135  /* and the capabilities */
136  impl->HasCaptureSupport = SDL_TRUE;
137  impl->OnlyHasDefaultOutputDevice = 1;
138  impl->OnlyHasDefaultCaptureDevice = 1;
139 
140  return 1; /* this audio target is available. */
141 }
142 
144  "android", "SDL Android audio driver", ANDROIDAUDIO_Init, 0
145 };
146 
147 /* Pause (block) all non already paused audio devices by taking their mixer lock */
148 void ANDROIDAUDIO_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 (SDL_AtomicGet(&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  SDL_AtomicSet(&audioDevice->paused, 1);
161  private->resume = SDL_TRUE;
162  }
163  }
164 
165  if(captureDevice != NULL && captureDevice->hidden != NULL) {
166  private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
167  if (SDL_AtomicGet(&captureDevice->paused)) {
168  /* The device is already paused, leave it alone */
169  private->resume = SDL_FALSE;
170  }
171  else {
172  SDL_LockMutex(captureDevice->mixer_lock);
173  SDL_AtomicSet(&captureDevice->paused, 1);
174  private->resume = SDL_TRUE;
175  }
176  }
177 }
178 
179 /* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
181 {
182  /* TODO: Handle multiple devices? */
183  struct SDL_PrivateAudioData *private;
184  if(audioDevice != NULL && audioDevice->hidden != NULL) {
185  private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
186  if (private->resume) {
187  SDL_AtomicSet(&audioDevice->paused, 0);
188  private->resume = SDL_FALSE;
189  SDL_UnlockMutex(audioDevice->mixer_lock);
190  }
191  }
192 
193  if(captureDevice != NULL && captureDevice->hidden != NULL) {
194  private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
195  if (private->resume) {
196  SDL_AtomicSet(&captureDevice->paused, 0);
197  private->resume = SDL_FALSE;
198  SDL_UnlockMutex(captureDevice->mixer_lock);
199  }
200  }
201 }
202 
203 #else
204 
207 
208 #endif /* SDL_AUDIO_DRIVER_ANDROID */
209 
210 /* vi: set ts=4 sw=4 expandtab: */
211 
SDL_AudioDevice::paused
SDL_atomic_t paused
Definition: SDL_sysaudio.h:149
SDL_FirstAudioFormat
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1647
SDL_AudioDriverImpl::HasCaptureSupport
int HasCaptureSupport
Definition: SDL_sysaudio.h:90
SDL_LockMutex
#define SDL_LockMutex
Definition: SDL_dynapi_overrides.h:260
SDL_AudioDriverImpl::FlushCapture
void(* FlushCapture)(_THIS)
Definition: SDL_sysaudio.h:76
NULL
#define NULL
Definition: begin_code.h:167
handle
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
SDL_AudioSpec::format
SDL_AudioFormat format
Definition: SDL_audio.h:181
SDL_AudioDriverImpl::OpenDevice
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
SDL_AudioDevice::hidden
struct SDL_PrivateAudioData * hidden
Definition: SDL_sysaudio.h:170
SDL_NextAudioFormat
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1659
SDL_PrivateAudioData::iscapture
SDL_bool iscapture
Definition: SDL_qsa_audio.h:37
SDL_AudioFormat
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
AudioBootStrap
Definition: SDL_sysaudio.h:176
SDL_PrivateAudioData
Definition: SDL_alsa_audio.h:33
AUDIO_U8
#define AUDIO_U8
Definition: SDL_audio.h:89
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
buffer
GLuint buffer
Definition: SDL_opengl_glext.h:533
Android_JNI_GetAudioBuffer
void * Android_JNI_GetAudioBuffer(void)
SDL_audio.h
private
#define private
Definition: SDL_naclaudio.h:34
SDL_AudioDriverImpl
Definition: SDL_sysaudio.h:65
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
Android_JNI_FlushCapturedAudio
void Android_JNI_FlushCapturedAudio(void)
SDL_AudioDriverImpl::OnlyHasDefaultOutputDevice
int OnlyHasDefaultOutputDevice
Definition: SDL_sysaudio.h:91
SDL_assert.h
SDL_CalculateAudioSpec
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1668
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_AudioDriverImpl::PlayDevice
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
Android_JNI_OpenAudioDevice
int Android_JNI_OpenAudioDevice(int iscapture, SDL_AudioSpec *spec)
SDL_AudioDriverImpl::OnlyHasDefaultCaptureDevice
int OnlyHasDefaultCaptureDevice
Definition: SDL_sysaudio.h:92
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
spec
SDL_AudioSpec spec
Definition: loopwave.c:31
ANDROIDAUDIO_PauseDevices
void ANDROIDAUDIO_PauseDevices(void)
Definition: SDL_androidaudio.c:206
SDL_AudioDriverImpl::CaptureFromDevice
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:75
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
AUDIO_S16
#define AUDIO_S16
Definition: SDL_audio.h:96
Android_JNI_CloseAudioDevice
void Android_JNI_CloseAudioDevice(const int iscapture)
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_AudioDriverImpl::GetDeviceBuf
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74
Android_JNI_WriteAudioBuffer
void Android_JNI_WriteAudioBuffer(void)
ANDROIDAUDIO_ResumeDevices
void ANDROIDAUDIO_ResumeDevices(void)
Definition: SDL_androidaudio.c:205
SDL_androidaudio.h
SDL_PrivateAudioData::resume
int resume
Definition: SDL_androidaudio.h:34
ANDROIDAUDIO_bootstrap
AudioBootStrap ANDROIDAUDIO_bootstrap
SDL_AtomicSet
#define SDL_AtomicSet
Definition: SDL_dynapi_overrides.h:67
SDL_AtomicGet
#define SDL_AtomicGet
Definition: SDL_dynapi_overrides.h:68
SDL_UnlockMutex
#define SDL_UnlockMutex
Definition: SDL_dynapi_overrides.h:262
SDL_AudioDevice::mixer_lock
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:159
AUDIO_F32
#define AUDIO_F32
Definition: SDL_audio.h:114
SDL_AudioDriverImpl::CloseDevice
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
Android_JNI_CaptureAudioBuffer
int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
SDL_AudioDevice
Definition: SDL_sysaudio.h:131
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179