Made audio single-threaded - ITCRASHES nOW, and doesn't work with Android 1.6

This commit is contained in:
pelya
2010-06-08 20:09:35 +03:00
parent 3efc812191
commit 3aa634d175
9 changed files with 116 additions and 541 deletions
@@ -20,6 +20,7 @@
#include "game.h"
#include "SDL.h"
#include <stdlib.h>
#include <android/log.h>
using namespace std;
@@ -35,6 +35,9 @@ Mixer & Mixer::mixer()
}
Mixer::Mixer() {
enabled = false;
return;
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
printf("Couldn't initialize SDL audio subsystem: %s\n", SDL_GetError());
exit(1);
@@ -41,18 +41,20 @@ Mix_Chunk *SoundDB::loadWav( string fn ) {
if ( searchResult ) {
return searchResult;
}
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", (string( "Loading sound " ) + fn).c_str() );
string fn1 = fn;
// Check if file exist
FILE * inputFile = fopen( fn.c_str(), "rb");
FILE * inputFile = fopen( fn1.c_str(), "rb");
if (!inputFile) {
if( fn.size() > 4 && fn.find(".wav") != string::npos ) {
fn = fn.substr( 0, fn.size() - 4 ) + ".ogg";
inputFile = fopen( fn.c_str(), "rb");
if( fn1.size() > 4 && fn1.find(".wav") != string::npos ) {
fn1 = fn1.substr( 0, fn1.size() - 4 ) + ".ogg";
inputFile = fopen( fn1.c_str(), "rb");
}
if (!inputFile) {
cout << "ERROR: file " << fn << " does not exist!" << endl;
cout << "ERROR: file " << fn1 << " does not exist!" << endl;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load sound " ) + fn).c_str() );
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load sound " ) + fn1).c_str() );
#endif
exit(1);
}
@@ -60,11 +62,11 @@ Mix_Chunk *SoundDB::loadWav( string fn ) {
fclose(inputFile);
// TODO: error-handling
Mix_Chunk *newSound = Mix_LoadWAV( fn.c_str() );
Mix_Chunk *newSound = Mix_LoadWAV( fn1.c_str() );
if( !newSound ) {
cout << "ERROR: file " << fn << " cannot be loaded!" << endl;
cout << "ERROR: file " << fn1 << " cannot be loaded!" << endl;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load sound " ) + fn).c_str() );
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load sound " ) + fn1).c_str() );
#endif
exit(1);
}
@@ -51,32 +51,34 @@ SDL_Surface *SurfaceDB::loadSurface( string fn, bool alpha ) {
if ( searchResult ) {
return searchResult;
}
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", (string( "Loading image " ) + fn).c_str() );
string fn1 = fn;
bool isPNG = false;
// Check if file exist
FILE * inputFile = fopen( fn.c_str(), "rb");
FILE * inputFile = fopen( fn1.c_str(), "rb");
if (!inputFile) {
if( fn.size() > 4 && fn.find(".bmp") != string::npos ) {
if( fn1.size() > 4 && fn1.find(".bmp") != string::npos ) {
isPNG = true;
fn = fn.substr( 0, fn.size() - 4 ) + ".png";
inputFile = fopen( fn.c_str(), "rb");
fn1 = fn1.substr( 0, fn1.size() - 4 ) + ".png";
inputFile = fopen( fn1.c_str(), "rb");
}
if (!inputFile) {
cout << "ERROR: file " << fn << " does not exist!" << endl;
cout << "ERROR: file " << fn1 << " does not exist!" << endl;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load image " ) + fn).c_str() );
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load image " ) + fn1).c_str() );
#endif
exit(1);
}
}
fclose(inputFile);
SDL_Surface *newSurface = isPNG ? IMG_Load( fn.c_str() ) : SDL_LoadBMP( fn.c_str() );
SDL_Surface *newSurface = isPNG ? IMG_Load( fn1.c_str() ) : SDL_LoadBMP( fn1.c_str() );
if( newSurface == NULL )
{
cout << "ERROR: Cannot load image " << fn << endl;
cout << "ERROR: Cannot load image " << fn1 << endl;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load image " ) + fn).c_str() );
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load image " ) + fn1).c_str() );
#endif
exit(1);
}
@@ -77,52 +77,33 @@ AudioBootStrap ANDROIDAUD_bootstrap = {
};
static SDL_mutex * audioMutex = NULL;
static SDL_cond * audioCond = NULL;
static SDL_cond * audioCond2 = NULL;
static unsigned char * audioBuffer = NULL;
static size_t audioBufferSize = 0;
static SDL_AudioSpec *audioFormat = NULL;
static int audioInitialized = 0;
static int audioPlayed = 0;
// Extremely wicked JNI environment to call Java functions from C code
static jbyteArray audioBufferJNI = NULL;
static JNIEnv * jniEnv = NULL;
static jclass JavaAudioThreadClass = NULL;
static jobject JavaAudioThread = NULL;
static jmethodID JavaFillBuffer = NULL;
static jmethodID JavaInitAudio = NULL;
static jmethodID JavaDeinitAudio = NULL;
static Uint8 *ANDROIDAUD_GetAudioBuf(_THIS)
{
return(this->hidden->mixbuf);
return(audioBuffer);
}
static void ANDROIDAUD_CloseAudio(_THIS)
{
SDL_mutex * audioMutex1;
if( audioMutex != NULL )
{
audioMutex1 = audioMutex;
SDL_mutexP(audioMutex1);
audioInitialized = 0;
SDL_CondSignal(audioCond);
SDL_CondSignal(audioCond2);
audioMutex = NULL;
SDL_DestroyCond(audioCond);
SDL_DestroyCond(audioCond2);
audioCond = NULL;
audioCond2 = NULL;
audioFormat = NULL;
// TODO: this crashes JNI, so we're just memleaking it
/*
(*jniEnv)->ReleaseByteArrayElements(jniEnv, audioBufferJNI, (jbyte *)audioBuffer, 0);
(*jniEnv)->DeleteGlobalRef(jniEnv, audioBufferJNI);
*/
jniEnv = NULL;
audioBufferJNI = NULL;
audioBuffer = NULL;
audioBufferSize = 0;
SDL_mutexV(audioMutex1);
SDL_DestroyMutex(audioMutex1);
}
(*jniEnv)->DeleteGlobalRef(jniEnv, audioBufferJNI);
audioBufferJNI = NULL;
audioBuffer = NULL;
audioBufferSize = 0;
(*jniEnv)->CallIntMethod( jniEnv, JavaAudioThread, JavaDeinitAudio );
if ( this->hidden != NULL ) {
SDL_free(this->hidden);
this->hidden = NULL;
@@ -131,6 +112,15 @@ static void ANDROIDAUD_CloseAudio(_THIS)
static int ANDROIDAUD_OpenAudio(_THIS, const char *devname, int iscapture)
{
SDL_AudioSpec *audioFormat = &this->spec;
jintArray initArray = NULL;
int initData[4] = { 0, 0, 0, 0 }; // { rate, channels, encoding, bufsize };
jobject * bufferObj;
jboolean isCopy = JNI_TRUE;
unsigned char *audioBuffer;
int audioBufferSize;
int bytesPerSample;
this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden));
if ( this->hidden == NULL ) {
SDL_OutOfMemory();
@@ -143,39 +133,39 @@ static int ANDROIDAUD_OpenAudio(_THIS, const char *devname, int iscapture)
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "Application requested unsupported audio format - only S8 and S16 are supported");
return (-1); // TODO: enable format conversion? Don't know how to do that in SDL
}
if( audioMutex == NULL )
initData[0] = audioFormat->freq;
initData[1] = audioFormat->channels;
bytesPerSample = (audioFormat->format & 0xFF) / 8;
initData[2] = ( bytesPerSample == 2 ) ? 1 : 0;
audioFormat->format = ( bytesPerSample == 2 ) ? AUDIO_S16 : AUDIO_S8;
initData[3] = audioFormat->size;
initArray = (*jniEnv)->NewIntArray(jniEnv, 4);
(*jniEnv)->SetIntArrayRegion(jniEnv, initArray, 0, 4, (jint *)initData);
bufferObj = (*jniEnv)->CallObjectMethod( jniEnv, JavaAudioThread, JavaInitAudio, initArray );
if( ! bufferObj )
{
audioInitialized = 0;
audioFormat = &this->spec;
audioMutex = SDL_CreateMutex();
audioCond = SDL_CreateCond();
audioCond2 = SDL_CreateCond();
audioPlayed == 0;
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_OpenAudio(): failed to get audio buffer from JNI");
ANDROIDAUD_CloseAudio(this);
return(-1);
}
SDL_mutexP(audioMutex);
while( !audioInitialized )
{
if( SDL_CondWaitTimeout( audioCond, audioMutex, 5000 ) != 0 )
{
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_OpenAudio() failed! timeout when waiting callback");
SDL_mutexV(audioMutex);
ANDROIDAUD_CloseAudio(this);
return(-1);
}
}
audioBufferJNI = (jbyteArray*)(*jniEnv)->NewGlobalRef(jniEnv, bufferObj);
audioBufferSize = (*jniEnv)->GetArrayLength(jniEnv, audioBufferJNI);
audioBuffer = (unsigned char *) (*jniEnv)->GetByteArrayElements(jniEnv, audioBufferJNI, &isCopy);
if( isCopy == JNI_TRUE )
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "ANDROIDAUD_OpenAudio(): JNI returns a copy of byte array - no audio will be played");
bytesPerSample = (audioFormat->format & 0xFF) / 8;
audioFormat->samples = audioBufferSize / bytesPerSample / audioFormat->channels;
audioFormat->size = audioBufferSize;
SDL_memset(audioBuffer, audioFormat->silence, audioFormat->size);
SDL_CalculateAudioSpec(&this->spec);
this->hidden->mixbuf = audioBuffer;
this->hidden->mixlen = audioBufferSize;
audioFormat = NULL;
SDL_mutexV(audioMutex);
return(1);
}
@@ -187,19 +177,16 @@ static void ANDROIDAUD_WaitAudio(_THIS)
static void ANDROIDAUD_PlayAudio(_THIS)
{
SDL_mutexP(audioMutex);
(*jniEnv)->ReleaseByteArrayElements(jniEnv, audioBufferJNI, (jbyte *)audioBuffer, 0);
audioBuffer == NULL;
//audioBuffer = this->hidden->mixbuf;
//audioBufferSize = this->hidden->mixlen;
(*jniEnv)->CallIntMethod( jniEnv, JavaAudioThread, JavaDeinitAudio );
audioPlayed = 1;
SDL_CondSignal(audioCond2);
SDL_CondWaitTimeout( audioCond, audioMutex, 1000 );
jboolean isCopy = JNI_TRUE;
audioBuffer = (unsigned char *) (*jniEnv)->GetByteArrayElements(jniEnv, audioBufferJNI, &isCopy);
if( isCopy == JNI_TRUE )
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_PlayAudio() JNI returns a copy of byte array - that's slow");
this->hidden->mixbuf = audioBuffer;
SDL_mutexV(audioMutex);
}
#ifndef SDL_JAVA_PACKAGE_PATH
@@ -209,125 +196,22 @@ static void ANDROIDAUD_PlayAudio(_THIS)
#define JAVA_EXPORT_NAME1(name,package) JAVA_EXPORT_NAME2(name,package)
#define JAVA_EXPORT_NAME(name) JAVA_EXPORT_NAME1(name,SDL_JAVA_PACKAGE_PATH)
extern jintArray JAVA_EXPORT_NAME(AudioThread_nativeAudioInit) (JNIEnv * env, jobject jobj)
extern int JAVA_EXPORT_NAME(AudioThread_nativeAudioInitJavaCallbacks) (JNIEnv * env, jobject thiz)
{
jintArray ret = NULL;
int initData[4] = { 0, 0, 0, 0 }; // { rate, channels, encoding, bufsize };
__android_log_print(ANDROID_LOG_INFO, "libSDL", "nativeAudioInitJavaCallbacks(): enter");
jniEnv = env;
JavaAudioThread = thiz;
if( audioMutex == NULL )
return ret;
JavaAudioThreadClass = (*jniEnv)->GetObjectClass(jniEnv, thiz);
JavaFillBuffer = (*jniEnv)->GetMethodID(jniEnv, JavaAudioThreadClass, "fillBuffer", "()I");
JavaInitAudio = (*jniEnv)->GetMethodID(jniEnv, JavaAudioThreadClass, "initAudio", "([I)[B");
JavaDeinitAudio = (*jniEnv)->GetMethodID(jniEnv, JavaAudioThreadClass, "deinitAudio", "()I");
if( ! JavaFillBuffer )
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "nativeAudioInitJavaCallbacks(): JavaFillBuffer is NULL");
if( ! JavaInitAudio )
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "nativeAudioInitJavaCallbacks(): JavaInitAudio is NULL");
if( ! JavaInitAudio )
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "nativeAudioInitJavaCallbacks(): JavaDeinitAudio is NULL");
SDL_mutexP(audioMutex);
if( audioInitialized == 0 )
{
initData[0] = audioFormat->freq;
initData[1] = audioFormat->channels;
int bytesPerSample = (audioFormat->format & 0xFF) / 8;
initData[2] = ( bytesPerSample == 2 ) ? 1 : 0;
audioFormat->format = ( bytesPerSample == 2 ) ? AUDIO_S16 : AUDIO_S8;
initData[3] = audioFormat->size;
ret=(*env)->NewIntArray(env, 4);
(*env)->SetIntArrayRegion(env, ret, 0, 4, (jint *)initData);
}
SDL_mutexV(audioMutex);
return (ret);
};
extern jint JAVA_EXPORT_NAME(AudioThread_nativeAudioInit2) (JNIEnv * env, jobject jobj, jbyteArray buf)
{
if( audioMutex == NULL )
return 0;
SDL_mutexP(audioMutex);
if( audioInitialized == 0 )
{
/* Allocate mixing buffer */
audioBufferJNI = (jbyteArray*)(*env)->NewGlobalRef(env, buf);
audioBufferSize = (*env)->GetArrayLength(env, audioBufferJNI);
jboolean isCopy = JNI_TRUE;
audioBuffer = (unsigned char *) (*env)->GetByteArrayElements(env, audioBufferJNI, &isCopy);
if( isCopy == JNI_TRUE )
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "AudioThread_nativeAudioInit2() JNI returns a copy of byte array - no audio will be played");
jniEnv = env;
int bytesPerSample = (audioFormat->format & 0xFF) / 8;
audioFormat->samples = audioBufferSize / bytesPerSample / audioFormat->channels;
audioFormat->size = audioBufferSize;
SDL_memset(audioBuffer, audioFormat->silence, audioFormat->size);
char t[512];
//sprintf(t, "AudioThread_nativeAudioInit2() got byte array from JNI: size %i samples %i direct memory %i", audioBufferSize, audioFormat->samples, (isCopy == JNI_FALSE) );
/*
audioBuffer = (Uint8 *) SDL_AllocAudioMem(audioBufferSize);
if ( audioBuffer == NULL ) {
SDL_mutexV(audioMutex);
return NULL;
}
ret = (*env)->NewDirectByteBuffer(env, audioBuffer, audioBufferSize);
*/
audioInitialized = 1;
SDL_CondSignal(audioCond);
}
SDL_mutexV(audioMutex);
return 0;
}
extern jint JAVA_EXPORT_NAME(AudioThread_nativeAudioBufferLock) ( JNIEnv * env, jobject jobj )
{
int ret = 0;
if( audioMutex == NULL )
return(-1);
SDL_mutexP(audioMutex);
if( !audioInitialized )
{
SDL_mutexV(audioMutex);
SDL_CondSignal(audioCond);
return (-1);
}
if( audioPlayed == 0 )
SDL_CondWaitTimeout(audioCond2, audioMutex, 1000);
if( audioBuffer == NULL ) // Should not happen
ret = 0;
else
{
(*jniEnv)->ReleaseByteArrayElements(jniEnv, audioBufferJNI, (jbyte *)audioBuffer, 0);
audioBuffer == NULL;
ret = audioBufferSize;
}
return ret;
};
extern jint JAVA_EXPORT_NAME(AudioThread_nativeAudioBufferUnlock) ( JNIEnv * env, jobject jobj )
{
if( audioMutex == NULL )
return(-1);
jboolean isCopy = JNI_TRUE;
audioBuffer = (unsigned char *) (*env)->GetByteArrayElements(env, audioBufferJNI, &isCopy);
if( isCopy == JNI_TRUE )
__android_log_print(ANDROID_LOG_INFO, "libSDL", "AudioThread_nativeAudioBufferUnlock() JNI returns a copy of byte array - that's slow");
audioPlayed = 0;
SDL_mutexV(audioMutex);
SDL_CondSignal(audioCond);
return 0;
}
@@ -27,9 +27,6 @@
#include "../SDL_sysaudio.h"
struct SDL_PrivateAudioData {
/* The file descriptor for the audio device */
Uint8 *mixbuf;
Uint32 mixlen;
};
#endif /* _SDL_androidaudio_h */
@@ -238,7 +238,6 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeDone) ( JNIEnv* env, jobject thiz )
void
JAVA_EXPORT_NAME(DemoRenderer_nativeInitJavaCallbacks) ( JNIEnv* env, jobject thiz )
{
char classPath[1024];
JavaEnv = env;
JavaRenderer = thiz;
@@ -255,293 +254,3 @@ int CallJavaSwapBuffers()
}
/* Stuff from SDL 1.2 */
/*
// Pointer to in-memory video surface
static int memX = 0;
static int memY = 0;
// In-memory surfaces
static void * memBuffer1 = NULL;
static void * memBuffer2 = NULL;
static void * memBuffer = NULL;
static int sdl_opengl = 0;
// Some wicked GLES stuff
static GLuint texture = 0;
SDL_Surface *ANDROID_SetVideoMode(_THIS, SDL_Surface *current,
int width, int height, int bpp, Uint32 flags)
{
__android_log_print(ANDROID_LOG_INFO, "libSDL", "SDL_SetVideoMode(): application requested mode %dx%d", width, height);
if ( memBuffer1 )
SDL_free( memBuffer1 );
if ( memBuffer2 )
SDL_free( memBuffer2 );
memBuffer = memBuffer1 = memBuffer2 = NULL;
sdl_opengl = (flags & SDL_OPENGL) ? 1 : 0;
memX = width;
memY = height;
if( ! sdl_opengl )
{
memBuffer1 = SDL_malloc(memX * memY * (bpp / 8));
if ( ! memBuffer1 ) {
__android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate buffer for requested mode");
SDL_SetError("Couldn't allocate buffer for requested mode");
return(NULL);
}
SDL_memset(memBuffer1, 0, memX * memY * (bpp / 8));
if( flags & SDL_DOUBLEBUF )
{
memBuffer2 = SDL_malloc(memX * memY * (bpp / 8));
if ( ! memBuffer2 ) {
__android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate buffer for requested mode");
SDL_SetError("Couldn't allocate buffer for requested mode");
return(NULL);
}
SDL_memset(memBuffer2, 0, memX * memY * (bpp / 8));
}
memBuffer = memBuffer1;
}
if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) {
if(memBuffer)
SDL_free(memBuffer);
memBuffer = NULL;
__android_log_print(ANDROID_LOG_INFO, "libSDL", "Couldn't allocate new pixel format for requested mode");
SDL_SetError("Couldn't allocate new pixel format for requested mode");
return(NULL);
}
current->flags = (flags & SDL_FULLSCREEN) | (flags & SDL_DOUBLEBUF) | (flags & SDL_OPENGL);
current->w = width;
current->h = height;
current->pitch = memX * (bpp / 8);
current->pixels = memBuffer;
SdlGlRenderInit();
return(current);
}
SDL_Rect **ANDROID_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
{
if(format->BitsPerPixel != 16)
return NULL;
return SDL_modelist;
}
static int ANDROID_FlipHWSurface(_THIS, SDL_Surface *surface)
{
if( ! sdl_opengl )
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, memX, memY, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, memBuffer);
if( sWindowHeight < memY || sWindowWidth < memX )
glDrawTexiOES(0, 0, 1, sWindowWidth, sWindowHeight); // Larger than screen - shrink to fit
else
glDrawTexiOES(0, sWindowHeight-memY, 1, memX, memY); // Smaller than screen - do not scale, it's faster that way
if( surface->flags & SDL_DOUBLEBUF )
{
if( memBuffer == memBuffer1 )
memBuffer = memBuffer2;
else
memBuffer = memBuffer1;
surface->pixels = memBuffer;
}
}
CallJavaSwapBuffers();
processAndroidTrackballKeyDelays( -1, 0 );
SDL_Delay(10);
return(0);
};
int ANDROID_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
{
return(1);
}
// TODO: use OpenGL textures here
static int ANDROID_AllocHWSurface(_THIS, SDL_Surface *surface)
{
return(-1);
}
static void ANDROID_FreeHWSurface(_THIS, SDL_Surface *surface)
{
return;
}
static int ANDROID_LockHWSurface(_THIS, SDL_Surface *surface)
{
return(0);
}
static void ANDROID_UnlockHWSurface(_THIS, SDL_Surface *surface)
{
return;
}
static void ANDROID_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
{
ANDROID_FlipHWSurface(this, SDL_VideoSurface);
}
void SdlGlRenderInit()
{
// Set up an array of values to use as the sprite vertices.
static GLfloat vertices[] =
{
0, 0,
1, 0,
0, 1,
1, 1,
};
// Set up an array of values for the texture coordinates.
static GLfloat texcoords[] =
{
0, 0,
1, 0,
0, 1,
1, 1,
};
static GLint texcoordsCrop[] =
{
0, 0, 0, 0,
};
static float clearColor = 0.0f;
static int clearColorDir = 1;
int textX, textY;
void * memBufferTemp;
if( !sdl_opengl && memBuffer )
{
// Texture sizes should be 2^n
textX = memX;
textY = memY;
if( textX <= 256 )
textX = 256;
else if( textX <= 512 )
textX = 512;
else
textX = 1024;
if( textY <= 256 )
textY = 256;
else if( textY <= 512 )
textY = 512;
else
textY = 1024;
glViewport(0, 0, textX, textY);
glClearColor(0,0,0,0);
// Set projection
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
#if defined(GL_VERSION_ES_CM_1_0)
#define glOrtho glOrthof
#endif
glOrtho( 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f );
// Now Initialize modelview matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_DITHER);
glDisable(GL_MULTISAMPLE);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
void * textBuffer = SDL_malloc( textX*textY*2 );
SDL_memset( textBuffer, 0, textX*textY*2 );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textX, textY, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textBuffer);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
texcoordsCrop[0] = 0;
texcoordsCrop[1] = memY;
texcoordsCrop[2] = memX;
texcoordsCrop[3] = -memY;
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, texcoordsCrop);
glFinish();
SDL_free( textBuffer );
}
}
// Stubs to get rid of crashing in OpenGL mode
// The implementation dependent data for the window manager cursor
struct WMcursor {
int unused ;
};
void ANDROID_FreeWMCursor(_THIS, WMcursor *cursor) {
SDL_free (cursor);
return;
}
WMcursor * ANDROID_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) {
WMcursor * cursor;
cursor = (WMcursor *) SDL_malloc (sizeof (WMcursor)) ;
if (cursor == NULL) {
SDL_OutOfMemory () ;
return NULL ;
}
return cursor;
}
int ANDROID_ShowWMCursor(_THIS, WMcursor *cursor) {
return 1;
}
void ANDROID_WarpWMCursor(_THIS, Uint16 x, Uint16 y) { }
void ANDROID_MoveWMCursor(_THIS, int x, int y) { }
static void ANDROID_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
*/
+17 -34
View File
@@ -16,9 +16,7 @@ import java.io.*;
import java.nio.ByteBuffer;
// TODO: make audio single-threaded, the same way as video
class AudioThread extends Thread {
class AudioThread {
private Activity mParent;
private AudioTrack mAudio;
@@ -30,26 +28,19 @@ class AudioThread extends Thread {
mParent = parent;
mAudio = null;
mAudioBuffer = null;
this.setPriority(Thread.MAX_PRIORITY);
this.start();
nativeAudioInitJavaCallbacks();
}
@Override
public void run()
public int fillBuffer()
{
mAudio.write( mAudioBuffer, 0, mAudioBuffer.length );
return 1;
}
public byte[] initAudio(int[] initParams)
{
while( !isInterrupted() )
{
if( mAudio == null )
{
int[] initParams = nativeAudioInit();
if( initParams == null )
{
try {
sleep(200);
} catch( java.lang.InterruptedException e ) { };
}
else
{
int rate = initParams[0];
int channels = initParams[1];
channels = ( channels == 1 ) ? AudioFormat.CHANNEL_CONFIGURATION_MONO :
@@ -61,7 +52,6 @@ class AudioThread extends Thread {
if( initParams[3] > bufSize )
bufSize = initParams[3];
mAudioBuffer = new byte[bufSize];
nativeAudioInit2(mAudioBuffer);
mAudio = new AudioTrack(AudioManager.STREAM_MUSIC,
rate,
channels,
@@ -69,29 +59,22 @@ class AudioThread extends Thread {
bufSize,
AudioTrack.MODE_STREAM );
mAudio.play();
}
}
else
{
int len = nativeAudioBufferLock();
if( len > 0 )
mAudio.write( mAudioBuffer, 0, len );
if( len < 0 )
break;
nativeAudioBufferUnlock();
}
}
return mAudioBuffer;
}
public int deinitAudio()
{
if( mAudio != null )
{
mAudio.stop();
mAudio.release();
mAudio = null;
}
mAudioBuffer = null;
return 1;
}
private native int[] nativeAudioInit();
private native int nativeAudioInit2(byte[] buf);
private native int nativeAudioBufferLock();
private native int nativeAudioBufferUnlock();
private native int nativeAudioInitJavaCallbacks();
}
+1 -7
View File
@@ -67,13 +67,7 @@ public class MainActivity extends Activity {
{
if( wakeLock != null )
wakeLock.release();
if( mAudioThread != null )
{
mAudioThread.interrupt();
try {
mAudioThread.join();
} catch( java.lang.InterruptedException e ) { };
}
if( mGLView != null )
mGLView.exitApp();
super.onStop();