SDL_androidaudio.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_ANDROID
/* Output audio to Android */
#include "SDL_assert.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_androidaudio.h"
#include "../../core/android/SDL_android.h"
#include <android/log.h>
static SDL_AudioDevice* audioDevice = NULL;
static SDL_AudioDevice* captureDevice = NULL;
static int
ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_AudioFormat test_format;
SDL_assert((captureDevice == NULL) || !iscapture);
SDL_assert((audioDevice == NULL) || iscapture);
if (iscapture) {
captureDevice = this;
} else {
audioDevice = this;
}
this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
test_format = SDL_FirstAudioFormat(this->spec.format);
while (test_format != 0) { /* no "UNKNOWN" constant */
if ((test_format == AUDIO_U8) ||
(test_format == AUDIO_S16) ||
(test_format == AUDIO_F32)) {
this->spec.format = test_format;
break;
}
test_format = SDL_NextAudioFormat();
}
if (test_format == 0) {
/* Didn't find a compatible format :( */
return SDL_SetError("No compatible audio format!");
}
if (Android_JNI_OpenAudioDevice(iscapture, &this->spec) < 0) {
return -1;
}
SDL_CalculateAudioSpec(&this->spec);
return 0;
}
static void
ANDROIDAUDIO_PlayDevice(_THIS)
{
Android_JNI_WriteAudioBuffer();
}
static Uint8 *
ANDROIDAUDIO_GetDeviceBuf(_THIS)
{
return Android_JNI_GetAudioBuffer();
}
static int
ANDROIDAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
return Android_JNI_CaptureAudioBuffer(buffer, buflen);
}
static void
ANDROIDAUDIO_FlushCapture(_THIS)
{
Android_JNI_FlushCapturedAudio();
}
static void
ANDROIDAUDIO_CloseDevice(_THIS)
{
/* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
so it's safe to terminate the Java side buffer and AudioTrack
*/
Android_JNI_CloseAudioDevice(this->iscapture);
if (this->iscapture) {
SDL_assert(captureDevice == this);
captureDevice = NULL;
} else {
SDL_assert(audioDevice == this);
audioDevice = NULL;
}
SDL_free(this->hidden);
}
static int
ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
impl->OpenDevice = ANDROIDAUDIO_OpenDevice;
impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
impl->CloseDevice = ANDROIDAUDIO_CloseDevice;
impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice;
impl->FlushCapture = ANDROIDAUDIO_FlushCapture;
/* and the capabilities */
impl->HasCaptureSupport = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultCaptureDevice = 1;
return 1; /* this audio target is available. */
}
AudioBootStrap ANDROIDAUDIO_bootstrap = {
"android", "SDL Android audio driver", ANDROIDAUDIO_Init, 0
};
/* Pause (block) all non already paused audio devices by taking their mixer lock */
void ANDROIDAUDIO_PauseDevices(void)
{
/* TODO: Handle multiple devices? */
struct SDL_PrivateAudioData *private;
if(audioDevice != NULL && audioDevice->hidden != NULL) {
private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
if (SDL_AtomicGet(&audioDevice->paused)) {
/* The device is already paused, leave it alone */
private->resume = SDL_FALSE;
}
else {
SDL_LockMutex(audioDevice->mixer_lock);
SDL_AtomicSet(&audioDevice->paused, 1);
private->resume = SDL_TRUE;
}
}
if(captureDevice != NULL && captureDevice->hidden != NULL) {
private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
if (SDL_AtomicGet(&captureDevice->paused)) {
/* The device is already paused, leave it alone */
private->resume = SDL_FALSE;
}
else {
SDL_LockMutex(captureDevice->mixer_lock);
SDL_AtomicSet(&captureDevice->paused, 1);
private->resume = SDL_TRUE;
}
}
}
/* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
void ANDROIDAUDIO_ResumeDevices(void)
{
/* TODO: Handle multiple devices? */
struct SDL_PrivateAudioData *private;
if(audioDevice != NULL && audioDevice->hidden != NULL) {
private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
if (private->resume) {
SDL_AtomicSet(&audioDevice->paused, 0);
private->resume = SDL_FALSE;
SDL_UnlockMutex(audioDevice->mixer_lock);
}
}
if(captureDevice != NULL && captureDevice->hidden != NULL) {
private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
if (private->resume) {
SDL_AtomicSet(&captureDevice->paused, 0);
private->resume = SDL_FALSE;
SDL_UnlockMutex(captureDevice->mixer_lock);
}
}
}
#else
void ANDROIDAUDIO_ResumeDevices(void) {}
void ANDROIDAUDIO_PauseDevices(void) {}
#endif /* SDL_AUDIO_DRIVER_ANDROID */
/* vi: set ts=4 sw=4 expandtab: */
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