Switch to loading OpenSLES dynamically

This commit is contained in:
UnknownShadow200 2021-01-29 23:04:41 +11:00
parent 0725c5122c
commit 980f98a06a
2 changed files with 50 additions and 21 deletions

View File

@ -134,7 +134,7 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback2 {
System.loadLibrary("classicube"); System.loadLibrary("classicube");
} catch (UnsatisfiedLinkError ex) { } catch (UnsatisfiedLinkError ex) {
ex.printStackTrace(); ex.printStackTrace();
showAlert("Failed to start", "Cannot load libclassicube.so: " + ex.getMessage()); showAlert("Failed to start", ex.getMessage());
return; return;
} }

View File

@ -17,6 +17,8 @@
#include "Window.h" #include "Window.h"
#endif #endif
#define QUOTE(x) #x
#define DefineDynFunc(sym) { QUOTE(sym), (void**)&_ ## sym }
int Audio_SoundsVolume, Audio_MusicVolume; int Audio_SoundsVolume, Audio_MusicVolume;
#if defined CC_BUILD_NOAUDIO #if defined CC_BUILD_NOAUDIO
@ -129,20 +131,18 @@ static const cc_string alLib = String_FromConst("libopenal.so");
static const cc_string alLib = String_FromConst("libopenal.so.1"); static const cc_string alLib = String_FromConst("libopenal.so.1");
#endif #endif
#define QUOTE(x) #x
#define DefineALFunc(sym) { QUOTE(sym), (void**)&_ ## sym }
static cc_bool LoadALFuncs(void) { static cc_bool LoadALFuncs(void) {
static const struct DynamicLibSym funcs[18] = { static const struct DynamicLibSym funcs[18] = {
DefineALFunc(alcCreateContext), DefineALFunc(alcMakeContextCurrent), DefineDynFunc(alcCreateContext), DefineDynFunc(alcMakeContextCurrent),
DefineALFunc(alcDestroyContext), DefineALFunc(alcOpenDevice), DefineDynFunc(alcDestroyContext), DefineDynFunc(alcOpenDevice),
DefineALFunc(alcCloseDevice), DefineALFunc(alcGetError), DefineDynFunc(alcCloseDevice), DefineDynFunc(alcGetError),
DefineALFunc(alGetError), DefineALFunc(alGenSources), DefineDynFunc(alGetError), DefineDynFunc(alGenSources),
DefineALFunc(alDeleteSources), DefineALFunc(alGetSourcei), DefineDynFunc(alDeleteSources), DefineDynFunc(alGetSourcei),
DefineALFunc(alSourcePlay), DefineALFunc(alSourceStop), DefineDynFunc(alSourcePlay), DefineDynFunc(alSourceStop),
DefineALFunc(alSourceQueueBuffers), DefineALFunc(alSourceUnqueueBuffers), DefineDynFunc(alSourceQueueBuffers), DefineDynFunc(alSourceUnqueueBuffers),
DefineALFunc(alGenBuffers), DefineALFunc(alDeleteBuffers), DefineDynFunc(alGenBuffers), DefineDynFunc(alDeleteBuffers),
DefineALFunc(alBufferData), DefineALFunc(alDistanceModel) DefineDynFunc(alBufferData), DefineDynFunc(alDistanceModel)
}; };
void* lib = DynamicLib_Load2(&alLib); void* lib = DynamicLib_Load2(&alLib);
@ -390,22 +390,51 @@ struct AudioContext {
SLBufferQueueItf bqPlayerQueue; SLBufferQueueItf bqPlayerQueue;
}; };
static SLresult (SLAPIENTRY *_slCreateEngine)(
SLObjectItf *pEngine,
SLuint32 numOptions,
const SLEngineOption *pEngineOptions,
SLuint32 numInterfaces,
const SLInterfaceID *pInterfaceIds,
const SLboolean *pInterfaceRequired
);
static SLInterfaceID* _SL_IID_NULL;
static SLInterfaceID* _SL_IID_PLAY;
static SLInterfaceID* _SL_IID_ENGINE;
static SLInterfaceID* _SL_IID_BUFFERQUEUE;
static const cc_string slLib = String_FromConst("libOpenSLES.so");
static cc_bool LoadSLFuncs(void) {
static const struct DynamicLibSym funcs[5] = {
DefineDynFunc(slCreateEngine), DefineDynFunc(SL_IID_NULL),
DefineDynFunc(SL_IID_PLAY), DefineDynFunc(SL_IID_ENGINE),
DefineDynFunc(SL_IID_BUFFERQUEUE)
};
void* lib = DynamicLib_Load2(&slLib);
if (!lib) { Logger_DynamicLibWarn("loading", &slLib); return false; }
return DynamicLib_GetAll(lib, funcs, Array_Elems(funcs));
}
static cc_bool Backend_Init(void) { static cc_bool Backend_Init(void) {
static const cc_string msg = String_FromConst("Failed to init OpenSLES. No audio will play.");
SLInterfaceID ids[1]; SLInterfaceID ids[1];
SLboolean req[1]; SLboolean req[1];
SLresult res; SLresult res;
if (slEngineObject) return true; if (slEngineObject) return true;
/* mixer doesn't use any effects */ if (!LoadSLFuncs()) { Logger_WarnFunc(&msg); return false; }
ids[0] = SL_IID_NULL; req[0] = SL_BOOLEAN_FALSE;
res = slCreateEngine(&slEngineObject, 0, NULL, 0, NULL, NULL); /* mixer doesn't use any effects */
ids[0] = *_SL_IID_NULL; req[0] = SL_BOOLEAN_FALSE;
res = _slCreateEngine(&slEngineObject, 0, NULL, 0, NULL, NULL);
if (res) { Logger_SimpleWarn(res, "creating OpenSL ES engine"); return false; } if (res) { Logger_SimpleWarn(res, "creating OpenSL ES engine"); return false; }
res = (*slEngineObject)->Realize(slEngineObject, SL_BOOLEAN_FALSE); res = (*slEngineObject)->Realize(slEngineObject, SL_BOOLEAN_FALSE);
if (res) { Logger_SimpleWarn(res, "realising OpenSL ES engine"); return false; } if (res) { Logger_SimpleWarn(res, "realising OpenSL ES engine"); return false; }
res = (*slEngineObject)->GetInterface(slEngineObject, SL_IID_ENGINE, &slEngineEngine); res = (*slEngineObject)->GetInterface(slEngineObject, *_SL_IID_ENGINE, &slEngineEngine);
if (res) { Logger_SimpleWarn(res, "initing OpenSL ES engine"); return false; } if (res) { Logger_SimpleWarn(res, "initing OpenSL ES engine"); return false; }
res = (*slEngineEngine)->CreateOutputMix(slEngineEngine, &slOutputObject, 1, ids, req); res = (*slEngineEngine)->CreateOutputMix(slEngineEngine, &slOutputObject, 1, ids, req);
@ -489,16 +518,16 @@ static cc_result Backend_SetFormat(struct AudioContext* ctx, struct AudioFormat*
dst.pLocator = &output; dst.pLocator = &output;
dst.pFormat = NULL; dst.pFormat = NULL;
ids[0] = SL_IID_BUFFERQUEUE; req[0] = SL_BOOLEAN_TRUE; ids[0] = *_SL_IID_BUFFERQUEUE; req[0] = SL_BOOLEAN_TRUE;
ids[1] = SL_IID_PLAY; req[1] = SL_BOOLEAN_TRUE; ids[1] = *_SL_IID_PLAY; req[1] = SL_BOOLEAN_TRUE;
res = (*slEngineEngine)->CreateAudioPlayer(slEngineEngine, &bqPlayerObject, &src, &dst, 2, ids, req); res = (*slEngineEngine)->CreateAudioPlayer(slEngineEngine, &bqPlayerObject, &src, &dst, 2, ids, req);
ctx->bqPlayerObject = bqPlayerObject; ctx->bqPlayerObject = bqPlayerObject;
if (res) return res; if (res) return res;
if ((res = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE))) return res; if ((res = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE))) return res;
if ((res = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &ctx->bqPlayerPlayer))) return res; if ((res = (*bqPlayerObject)->GetInterface(bqPlayerObject, *_SL_IID_PLAY, &ctx->bqPlayerPlayer))) return res;
if ((res = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &ctx->bqPlayerQueue))) return res; if ((res = (*bqPlayerObject)->GetInterface(bqPlayerObject, *_SL_IID_BUFFERQUEUE, &ctx->bqPlayerQueue))) return res;
return (*ctx->bqPlayerQueue)->RegisterCallback(ctx->bqPlayerQueue, OnBufferFinished, ctx); return (*ctx->bqPlayerQueue)->RegisterCallback(ctx->bqPlayerQueue, OnBufferFinished, ctx);
} }