android_frameworks_base/media/jni/audioeffect/android_media_AudioEffect.cpp

852 lines
27 KiB
C++
Raw Normal View History

/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
//#define LOG_NDEBUG 0
#define LOG_TAG "AudioEffects-JNI"
#include <utils/Log.h>
#include <nativehelper/jni.h>
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include "media/AudioEffect.h"
using namespace android;
#define AUDIOEFFECT_SUCCESS 0
#define AUDIOEFFECT_ERROR -1
#define AUDIOEFFECT_ERROR_ALREADY_EXISTS -2
#define AUDIOEFFECT_ERROR_NO_INIT -3
#define AUDIOEFFECT_ERROR_BAD_VALUE -4
#define AUDIOEFFECT_ERROR_INVALID_OPERATION -5
#define AUDIOEFFECT_ERROR_NO_MEMORY -6
#define AUDIOEFFECT_ERROR_DEAD_OBJECT -7
// ----------------------------------------------------------------------------
static const char* const kClassPathName = "android/media/AudioEffect";
struct fields_t {
// these fields provide access from C++ to the...
jclass clazzEffect; // AudioEffect class
jmethodID midPostNativeEvent; // event post callback method
jfieldID fidNativeAudioEffect; // stores in Java the native AudioEffect object
jfieldID fidJniData; // stores in Java additional resources used by the native AudioEffect
jclass clazzDesc; // AudioEffect.Descriptor class
jmethodID midDescCstor; // AudioEffect.Descriptor class constructor
};
static fields_t fields;
struct effect_callback_cookie {
jclass audioEffect_class; // AudioEffect class
jobject audioEffect_ref; // AudioEffect object instance
};
// ----------------------------------------------------------------------------
class AudioEffectJniStorage {
public:
effect_callback_cookie mCallbackData;
AudioEffectJniStorage() {
}
~AudioEffectJniStorage() {
}
};
static jint translateError(int code) {
switch(code) {
case NO_ERROR:
return AUDIOEFFECT_SUCCESS;
case ALREADY_EXISTS:
return AUDIOEFFECT_ERROR_ALREADY_EXISTS;
case NO_INIT:
return AUDIOEFFECT_ERROR_NO_INIT;
case BAD_VALUE:
return AUDIOEFFECT_ERROR_BAD_VALUE;
case INVALID_OPERATION:
return AUDIOEFFECT_ERROR_INVALID_OPERATION;
case NO_MEMORY:
return AUDIOEFFECT_ERROR_NO_MEMORY;
case DEAD_OBJECT:
return AUDIOEFFECT_ERROR_DEAD_OBJECT;
default:
return AUDIOEFFECT_ERROR;
}
}
// ----------------------------------------------------------------------------
static void effectCallback(int event, void* user, void *info) {
effect_param_t *p;
int arg1 = 0;
int arg2 = 0;
jobject obj = NULL;
jbyteArray array = NULL;
jbyte *bytes;
bool param;
size_t size;
effect_callback_cookie *callbackInfo = (effect_callback_cookie *)user;
JNIEnv *env = AndroidRuntime::getJNIEnv();
LOGV("effectCallback: callbackInfo %p, audioEffect_ref %p audioEffect_class %p",
callbackInfo,
callbackInfo->audioEffect_ref,
callbackInfo->audioEffect_class);
if (!user || !env) {
LOGW("effectCallback error user %p, env %p", user, env);
return;
}
switch (event) {
case AudioEffect::EVENT_CONTROL_STATUS_CHANGED:
if (info == 0) {
LOGW("EVENT_CONTROL_STATUS_CHANGED info == NULL");
goto effectCallback_Exit;
}
param = *(bool *)info;
arg1 = (int)param;
LOGV("EVENT_CONTROL_STATUS_CHANGED");
break;
case AudioEffect::EVENT_ENABLE_STATUS_CHANGED:
if (info == 0) {
LOGW("EVENT_ENABLE_STATUS_CHANGED info == NULL");
goto effectCallback_Exit;
}
param = *(bool *)info;
arg1 = (int)param;
LOGV("EVENT_ENABLE_STATUS_CHANGED");
break;
case AudioEffect::EVENT_PARAMETER_CHANGED:
if (info == 0) {
LOGW("EVENT_PARAMETER_CHANGED info == NULL");
goto effectCallback_Exit;
}
p = (effect_param_t *)info;
if (p->psize == 0 || p->vsize == 0) {
goto effectCallback_Exit;
}
// arg1 contains offset of parameter value from start of byte array
arg1 = sizeof(effect_param_t) + ((p->psize - 1) / sizeof(int) + 1) * sizeof(int);
size = arg1 + p->vsize;
array = env->NewByteArray(size);
if (array == NULL) {
LOGE("effectCallback: Couldn't allocate byte array for parameter data");
goto effectCallback_Exit;
}
bytes = env->GetByteArrayElements(array, NULL);
memcpy(bytes, p, size);
env->ReleaseByteArrayElements(array, bytes, 0);
obj = array;
LOGV("EVENT_PARAMETER_CHANGED");
break;
case AudioEffect::EVENT_ERROR:
LOGW("EVENT_ERROR");
break;
}
env->CallStaticVoidMethod(
callbackInfo->audioEffect_class,
fields.midPostNativeEvent,
callbackInfo->audioEffect_ref, event, arg1, arg2, obj);
effectCallback_Exit:
if (array) {
env->DeleteLocalRef(array);
}
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
}
// ----------------------------------------------------------------------------
// This function gets some field IDs, which in turn causes class initialization.
// It is called from a static block in AudioEffect, which won't run until the
// first time an instance of this class is used.
static void
android_media_AudioEffect_native_init(JNIEnv *env)
{
LOGV("android_media_AudioEffect_native_init");
fields.clazzEffect = NULL;
fields.clazzDesc = NULL;
// Get the AudioEffect class
jclass clazz = env->FindClass(kClassPathName);
if (clazz == NULL) {
LOGE("Can't find %s", kClassPathName);
return;
}
fields.clazzEffect = (jclass)env->NewGlobalRef(clazz);
// Get the postEvent method
fields.midPostNativeEvent = env->GetStaticMethodID(
fields.clazzEffect,
"postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.midPostNativeEvent == NULL) {
LOGE("Can't find AudioEffect.%s", "postEventFromNative");
return;
}
// Get the variables fields
// nativeTrackInJavaObj
fields.fidNativeAudioEffect = env->GetFieldID(
fields.clazzEffect,
"mNativeAudioEffect", "I");
if (fields.fidNativeAudioEffect == NULL) {
LOGE("Can't find AudioEffect.%s", "mNativeAudioEffect");
return;
}
// fidJniData;
fields.fidJniData = env->GetFieldID(
fields.clazzEffect,
"mJniData", "I");
if (fields.fidJniData == NULL) {
LOGE("Can't find AudioEffect.%s", "mJniData");
return;
}
clazz = env->FindClass("android/media/AudioEffect$Descriptor");
if (clazz == NULL) {
LOGE("Can't find android/media/AudioEffect$Descriptor class");
return;
}
fields.clazzDesc = (jclass)env->NewGlobalRef(clazz);
fields.midDescCstor
= env->GetMethodID(
fields.clazzDesc,
"<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (fields.midDescCstor == NULL) {
LOGE("Can't find android/media/AudioEffect$Descriptor class constructor");
return;
}
}
static jint
android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, jobjectArray javadesc)
{
LOGV("android_media_AudioEffect_native_setup");
AudioEffectJniStorage* lpJniStorage = NULL;
int lStatus = AUDIOEFFECT_ERROR_NO_MEMORY;
AudioEffect* lpAudioEffect = NULL;
jint* nId = NULL;
const char *typeStr = NULL;
const char *uuidStr = NULL;
effect_descriptor_t desc;
jobject jdesc;
char str[EFFECT_STRING_LEN_MAX];
jstring jdescType;
jstring jdescUuid;
jstring jdescConnect;
jstring jdescName;
jstring jdescImplementor;
if (type != NULL) {
typeStr = env->GetStringUTFChars(type, NULL);
if (typeStr == NULL) { // Out of memory
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
goto setup_failure;
}
}
if (uuid != NULL) {
uuidStr = env->GetStringUTFChars(uuid, NULL);
if (uuidStr == NULL) { // Out of memory
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
goto setup_failure;
}
}
if (typeStr == NULL && uuidStr == NULL) {
lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
goto setup_failure;
}
lpJniStorage = new AudioEffectJniStorage();
if (lpJniStorage == NULL) {
LOGE("setup: Error creating JNI Storage");
goto setup_failure;
}
lpJniStorage->mCallbackData.audioEffect_class = (jclass)env->NewGlobalRef(fields.clazzEffect);
// we use a weak reference so the AudioEffect object can be garbage collected.
lpJniStorage->mCallbackData.audioEffect_ref = env->NewGlobalRef(weak_this);
LOGV("setup: lpJniStorage: %p audioEffect_ref %p audioEffect_class %p, &mCallbackData %p",
lpJniStorage,
lpJniStorage->mCallbackData.audioEffect_ref,
lpJniStorage->mCallbackData.audioEffect_class,
&lpJniStorage->mCallbackData);
if (jId) {
nId = (jint *) env->GetPrimitiveArrayCritical(jId, NULL);
if (nId == NULL) {
LOGE("setup: Error retrieving id pointer");
lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
goto setup_failure;
}
} else {
LOGE("setup: NULL java array for id pointer");
lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
goto setup_failure;
}
// create the native AudioEffect object
lpAudioEffect = new AudioEffect(typeStr,
uuidStr,
priority,
effectCallback,
&lpJniStorage->mCallbackData,
sessionId,
0);
if (lpAudioEffect == NULL) {
LOGE("Error creating AudioEffect");
goto setup_failure;
}
lStatus = translateError(lpAudioEffect->initCheck());
if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) {
LOGE("AudioEffect initCheck failed %d", lStatus);
goto setup_failure;
}
nId[0] = lpAudioEffect->id();
env->ReleasePrimitiveArrayCritical(jId, nId, 0);
nId = NULL;
if (typeStr) {
env->ReleaseStringUTFChars(type, typeStr);
typeStr = NULL;
}
if (uuidStr) {
env->ReleaseStringUTFChars(uuid, uuidStr);
uuidStr = NULL;
}
// get the effect descriptor
desc = lpAudioEffect->descriptor();
AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);
jdescType = env->NewStringUTF(str);
AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);
jdescUuid = env->NewStringUTF(str);
if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
jdescConnect = env->NewStringUTF("Auxiliary");
} else {
jdescConnect = env->NewStringUTF("Insert");
}
jdescName = env->NewStringUTF(desc.name);
jdescImplementor = env->NewStringUTF(desc.implementor);
jdesc = env->NewObject(fields.clazzDesc,
fields.midDescCstor,
jdescType,
jdescUuid,
jdescConnect,
jdescName,
jdescImplementor);
env->DeleteLocalRef(jdescType);
env->DeleteLocalRef(jdescUuid);
env->DeleteLocalRef(jdescConnect);
env->DeleteLocalRef(jdescName);
env->DeleteLocalRef(jdescImplementor);
if (jdesc == NULL) {
LOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
goto setup_failure;
}
env->SetObjectArrayElement(javadesc, 0, jdesc);
env->SetIntField(thiz, fields.fidNativeAudioEffect, (int)lpAudioEffect);
env->SetIntField(thiz, fields.fidJniData, (int)lpJniStorage);
return AUDIOEFFECT_SUCCESS;
// failures:
setup_failure:
if (nId != NULL) {
env->ReleasePrimitiveArrayCritical(jId, nId, 0);
}
if (lpAudioEffect) {
delete lpAudioEffect;
}
env->SetIntField(thiz, fields.fidNativeAudioEffect, 0);
if (lpJniStorage) {
delete lpJniStorage;
}
env->SetIntField(thiz, fields.fidJniData, 0);
if (uuidStr != NULL) {
env->ReleaseStringUTFChars(uuid, uuidStr);
}
if (typeStr != NULL) {
env->ReleaseStringUTFChars(type, typeStr);
}
return lStatus;
}
// ----------------------------------------------------------------------------
static void android_media_AudioEffect_native_finalize(JNIEnv *env, jobject thiz) {
LOGV("android_media_AudioEffect_native_finalize jobject: %x\n", (int)thiz);
// delete the AudioEffect object
AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
thiz, fields.fidNativeAudioEffect);
if (lpAudioEffect) {
LOGV("deleting AudioEffect: %x\n", (int)lpAudioEffect);
delete lpAudioEffect;
}
// delete the JNI data
AudioEffectJniStorage* lpJniStorage = (AudioEffectJniStorage *)env->GetIntField(
thiz, fields.fidJniData);
if (lpJniStorage) {
LOGV("deleting pJniStorage: %x\n", (int)lpJniStorage);
delete lpJniStorage;
}
}
// ----------------------------------------------------------------------------
static void android_media_AudioEffect_native_release(JNIEnv *env, jobject thiz) {
// do everything a call to finalize would
android_media_AudioEffect_native_finalize(env, thiz);
// + reset the native resources in the Java object so any attempt to access
// them after a call to release fails.
env->SetIntField(thiz, fields.fidNativeAudioEffect, 0);
env->SetIntField(thiz, fields.fidJniData, 0);
}
static jint
android_media_AudioEffect_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
{
// retrieve the AudioEffect object
AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
thiz, fields.fidNativeAudioEffect);
if (lpAudioEffect == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for enable()");
return AUDIOEFFECT_ERROR_NO_INIT;
}
return translateError(lpAudioEffect->setEnabled(enabled));
}
static jboolean
android_media_AudioEffect_native_getEnabled(JNIEnv *env, jobject thiz)
{
// retrieve the AudioEffect object
AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
thiz, fields.fidNativeAudioEffect);
if (lpAudioEffect == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for getEnabled()");
return false;
}
return (jboolean)lpAudioEffect->getEnabled();
}
static jboolean
android_media_AudioEffect_native_hasControl(JNIEnv *env, jobject thiz)
{
// retrieve the AudioEffect object
AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
thiz, fields.fidNativeAudioEffect);
if (lpAudioEffect == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for hasControl()");
return false;
}
if (lpAudioEffect->initCheck() == NO_ERROR) {
return true;
} else {
return false;
}
}
static jint android_media_AudioEffect_native_setParameter(JNIEnv *env,
jobject thiz, int psize, jbyteArray pJavaParam, int vsize,
jbyteArray pJavaValue) {
// retrieve the AudioEffect object
jbyte* lpValue = NULL;
jbyte* lpParam = NULL;
jint lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
effect_param_t *p;
int voffset;
AudioEffect* lpAudioEffect = (AudioEffect *) env->GetIntField(thiz,
fields.fidNativeAudioEffect);
if (lpAudioEffect == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for setParameter()");
return AUDIOEFFECT_ERROR_NO_INIT;
}
if (psize == 0 || vsize == 0 || pJavaParam == NULL || pJavaValue == NULL) {
return AUDIOEFFECT_ERROR_BAD_VALUE;
}
// get the pointer for the param from the java array
lpParam = (jbyte *) env->GetPrimitiveArrayCritical(pJavaParam, NULL);
if (lpParam == NULL) {
LOGE("setParameter: Error retrieving param pointer");
goto setParameter_Exit;
}
// get the pointer for the value from the java array
lpValue = (jbyte *) env->GetPrimitiveArrayCritical(pJavaValue, NULL);
if (lpValue == NULL) {
LOGE("setParameter: Error retrieving value pointer");
goto setParameter_Exit;
}
voffset = ((psize - 1) / sizeof(int) + 1) * sizeof(int);
p = (effect_param_t *) malloc(sizeof(effect_param_t) + voffset + vsize);
memcpy(p->data, lpParam, psize);
p->psize = psize;
memcpy(p->data + voffset, lpValue, vsize);
p->vsize = vsize;
lStatus = lpAudioEffect->setParameter(p);
if (lStatus == NO_ERROR) {
lStatus = p->status;
}
free(p);
setParameter_Exit:
if (lpParam != NULL) {
env->ReleasePrimitiveArrayCritical(pJavaParam, lpParam, 0);
}
if (lpValue != NULL) {
env->ReleasePrimitiveArrayCritical(pJavaValue, lpValue, 0);
}
return translateError(lStatus);
}
static jint
android_media_AudioEffect_native_getParameter(JNIEnv *env,
jobject thiz, int psize, jbyteArray pJavaParam,
jintArray pJavaValueSize, jbyteArray pJavaValue) {
// retrieve the AudioEffect object
jbyte* lpParam = NULL;
jbyte* lpValue = NULL;
jbyte* lpValueSize = NULL;
jint lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
effect_param_t *p;
int voffset;
AudioEffect* lpAudioEffect = (AudioEffect *) env->GetIntField(thiz,
fields.fidNativeAudioEffect);
if (lpAudioEffect == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for getParameter()");
return AUDIOEFFECT_ERROR_NO_INIT;
}
if (psize == 0 || pJavaValueSize == NULL || pJavaParam == NULL || pJavaValue == NULL) {
return AUDIOEFFECT_ERROR_BAD_VALUE;
}
// get the pointer for the param from the java array
lpParam = (jbyte *) env->GetPrimitiveArrayCritical(pJavaParam, NULL);
if (lpParam == NULL) {
LOGE("getParameter: Error retrieving param pointer");
goto getParameter_Exit;
}
// get the pointer for the value from the java array
lpValue = (jbyte *) env->GetPrimitiveArrayCritical(pJavaValue, NULL);
if (lpValue == NULL) {
LOGE("getParameter: Error retrieving value pointer");
goto getParameter_Exit;
}
// get the pointer for the value size from the java array
lpValueSize = (jbyte *) env->GetPrimitiveArrayCritical(pJavaValueSize, NULL);
if (lpValueSize == NULL) {
LOGE("getParameter: Error retrieving value size pointer");
goto getParameter_Exit;
}
voffset = ((psize - 1) / sizeof(int) + 1) * sizeof(int);
p = (effect_param_t *) malloc(sizeof(effect_param_t) + voffset
+ lpValueSize[0]);
memcpy(p->data, lpParam, psize);
p->psize = psize;
p->vsize = lpValueSize[0];
lStatus = lpAudioEffect->getParameter(p);
if (lStatus == NO_ERROR) {
lStatus = p->status;
if (lStatus == NO_ERROR) {
memcpy(lpValue, p->data + voffset, p->vsize);
lpValueSize[0] = p->vsize;
}
}
free(p);
getParameter_Exit:
if (lpParam != NULL) {
env->ReleasePrimitiveArrayCritical(pJavaParam, lpParam, 0);
}
if (lpValue != NULL) {
env->ReleasePrimitiveArrayCritical(pJavaValue, lpValue, 0);
}
if (lpValueSize != NULL) {
env->ReleasePrimitiveArrayCritical(pJavaValueSize, lpValueSize, 0);
}
return translateError(lStatus);
}
static jint android_media_AudioEffect_native_command(JNIEnv *env, jobject thiz,
jint cmdCode, jint cmdSize, jbyteArray jCmdData, jintArray jReplySize,
jbyteArray jReplyData) {
jbyte* pCmdData = NULL;
jbyte* pReplyData = NULL;
jint* pReplySize = NULL;
jint lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
// retrieve the AudioEffect object
AudioEffect* lpAudioEffect = (AudioEffect *) env->GetIntField(thiz,
fields.fidNativeAudioEffect);
if (lpAudioEffect == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioEffect pointer for setParameter()");
return AUDIOEFFECT_ERROR_NO_INIT;
}
if ((cmdSize != 0 && jCmdData == NULL) || (jReplySize != NULL && jReplyData == NULL)) {
return AUDIOEFFECT_ERROR_BAD_VALUE;
}
// get the pointer for the command from the java array
if (cmdSize != 0) {
pCmdData = (jbyte *) env->GetPrimitiveArrayCritical(jCmdData, NULL);
if (pCmdData == NULL) {
LOGE("setParameter: Error retrieving command pointer");
goto command_Exit;
}
}
// get the pointer for the reply size from the java array
if (jReplySize != NULL) {
pReplySize = (jint *) env->GetPrimitiveArrayCritical(jReplySize, NULL);
if (pReplySize == NULL) {
LOGE("setParameter: Error retrieving reply pointer");
goto command_Exit;
}
}
// get the pointer for the reply from the java array
if (pReplySize != NULL && pReplySize[0] != 0 && jReplyData != NULL) {
pReplyData = (jbyte *) env->GetPrimitiveArrayCritical(jReplyData, NULL);
if (pReplyData == NULL) {
LOGE("setParameter: Error retrieving reply pointer");
goto command_Exit;
}
}
lStatus = translateError(lpAudioEffect->command((uint32_t)cmdCode,
(uint32_t)cmdSize,
pCmdData,
(uint32_t *)pReplySize,
pReplyData));
command_Exit:
if (pCmdData != NULL) {
env->ReleasePrimitiveArrayCritical(jCmdData, pCmdData, 0);
}
if (pReplyData != NULL) {
env->ReleasePrimitiveArrayCritical(jReplyData, pReplyData, 0);
}
if (pReplySize != NULL) {
env->ReleasePrimitiveArrayCritical(jReplySize, pReplySize, 0);
}
return lStatus;
}
static jobjectArray
android_media_AudioEffect_native_queryEffects(JNIEnv *env, jclass clazz)
{
effect_descriptor_t desc;
char str[EFFECT_STRING_LEN_MAX];
uint32_t numEffects;
uint32_t i = 0;
jstring jdescType;
jstring jdescUuid;
jstring jdescConnect;
jstring jdescName;
jstring jdescImplementor;
jobject jdesc;
AudioEffect::queryNumberEffects(&numEffects);
jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
if (ret == NULL) {
return ret;
}
LOGV("queryEffects() numEffects: %d", numEffects);
for (i = 0; i < numEffects; i++) {
Various fixes and improvements in audio effects implementation Effect API: - Use different definitions for audio device, channels, formats... in AudioSystem and EffectApi: Removed media/AudioCommon.h file created for initial version of EffectApi - Indicate audio session and output ID to effect library when calling EffectCreate(). Session ID can be useful to optimize the implementation of effect chains in the same audio session. Output ID can be used for effects implemented in audio hardware. - Renamed EffectQueryNext() function to EffectQueryEffect() and changed operating mode: now an index is passed for the queried effect instead of implicitly querying the next one. - Added CPU load and memory usage indication in effects descriptor - Added flags and commands to indicate changes in audio mode (ring tone, in call...) to effect engine - Added flag to indicate hardware accelerated effect implementation. - Renamed EffectFactoryApi.h to EffectsFactoryApi.h for consistency with EffectsFactory.c/h Effect libraries: - Reflected changes in Effect API - Several fixes in reverb implementation - Added build option TEST_EFFECT_LIBRARIES in makefile to prepare integration of actual effect library. - Replaced pointer by integer identifier for library handle returned by effects factory Audio effect framework: - Added support for audio session -1 in preparation of output stage effects configuration. - Reflected changes in Effect API - Removed volume ramp up/down when effect is inserted/removed: this has to be taken care of by effect engines. - Added some overflow verification on indexes used for deferred parameter updates via shared memory - Added hardcoded CPU and memory limit check when creating a new effect instance Change-Id: I43fee5182ee201384ea3479af6d0acb95092901d
2010-06-23 17:38:20 -07:00
if (AudioEffect::queryEffect(i, &desc) != NO_ERROR) {
goto queryEffects_failure;
}
AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);
jdescType = env->NewStringUTF(str);
AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);
jdescUuid = env->NewStringUTF(str);
if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
jdescConnect = env->NewStringUTF("Auxiliary");
} else {
jdescConnect = env->NewStringUTF("Insert");
}
jdescName = env->NewStringUTF(desc.name);
jdescImplementor = env->NewStringUTF(desc.implementor);
jdesc = env->NewObject(fields.clazzDesc,
fields.midDescCstor,
jdescType,
jdescUuid,
jdescConnect,
jdescName,
jdescImplementor);
env->DeleteLocalRef(jdescType);
env->DeleteLocalRef(jdescUuid);
env->DeleteLocalRef(jdescConnect);
env->DeleteLocalRef(jdescName);
env->DeleteLocalRef(jdescImplementor);
if (jdesc == NULL) {
LOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
goto queryEffects_failure;
}
env->SetObjectArrayElement(ret, i, jdesc);
}
return ret;
queryEffects_failure:
if (ret != NULL) {
env->DeleteLocalRef(ret);
}
return NULL;
}
// ----------------------------------------------------------------------------
// Dalvik VM type signatures
static JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_AudioEffect_native_init},
{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;)I",
(void *)android_media_AudioEffect_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize},
{"native_release", "()V", (void *)android_media_AudioEffect_native_release},
{"native_setEnabled", "(Z)I", (void *)android_media_AudioEffect_native_setEnabled},
{"native_getEnabled", "()Z", (void *)android_media_AudioEffect_native_getEnabled},
{"native_hasControl", "()Z", (void *)android_media_AudioEffect_native_hasControl},
{"native_setParameter", "(I[BI[B)I", (void *)android_media_AudioEffect_native_setParameter},
{"native_getParameter", "(I[B[I[B)I", (void *)android_media_AudioEffect_native_getParameter},
{"native_command", "(II[B[I[B)I", (void *)android_media_AudioEffect_native_command},
{"native_query_effects", "()[Ljava/lang/Object;", (void *)android_media_AudioEffect_native_queryEffects},
};
// ----------------------------------------------------------------------------
extern int register_android_media_visualizer(JNIEnv *env);
int register_android_media_AudioEffect(JNIEnv *env)
{
return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed\n");
goto bail;
}
assert(env != NULL);
if (register_android_media_AudioEffect(env) < 0) {
LOGE("ERROR: AudioEffect native registration failed\n");
goto bail;
}
if (register_android_media_visualizer(env) < 0) {
LOGE("ERROR: Visualizer native registration failed\n");
goto bail;
}
/* success -- return valid version number */
result = JNI_VERSION_1_4;
bail:
return result;
}