blob: 8463d94ad3ff21978546f0272be8c4eec70304e0 [file] [log] [blame]
Eric Laurentdf9b81c2010-07-02 08:12:41 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18
19//#define LOG_NDEBUG 0
20#define LOG_TAG "visualizers-JNI"
21
22#include <utils/Log.h>
23#include <nativehelper/jni.h>
24#include <nativehelper/JNIHelp.h>
25#include <android_runtime/AndroidRuntime.h>
John Grossman449725f2012-01-10 12:17:03 -080026#include <utils/threads.h>
Eric Laurentdf9b81c2010-07-02 08:12:41 -070027#include "media/Visualizer.h"
28
29using namespace android;
30
31#define VISUALIZER_SUCCESS 0
32#define VISUALIZER_ERROR -1
33#define VISUALIZER_ERROR_ALREADY_EXISTS -2
34#define VISUALIZER_ERROR_NO_INIT -3
35#define VISUALIZER_ERROR_BAD_VALUE -4
36#define VISUALIZER_ERROR_INVALID_OPERATION -5
37#define VISUALIZER_ERROR_NO_MEMORY -6
38#define VISUALIZER_ERROR_DEAD_OBJECT -7
39
40#define NATIVE_EVENT_PCM_CAPTURE 0
41#define NATIVE_EVENT_FFT_CAPTURE 1
John Grossman3540a012012-01-11 12:23:42 -080042#define NATIVE_EVENT_SERVER_DIED 2
Eric Laurentdf9b81c2010-07-02 08:12:41 -070043
44// ----------------------------------------------------------------------------
Eric Laurent1a5149e2010-09-21 18:18:20 -070045static const char* const kClassPathName = "android/media/audiofx/Visualizer";
Jean-Michel Trivibadca262013-09-20 10:48:55 -070046static const char* const kClassPeakRmsPathName =
47 "android/media/audiofx/Visualizer$MeasurementPeakRms";
Eric Laurentdf9b81c2010-07-02 08:12:41 -070048
49struct fields_t {
50 // these fields provide access from C++ to the...
51 jclass clazzEffect; // Visualizer class
52 jmethodID midPostNativeEvent; // event post callback method
53 jfieldID fidNativeVisualizer; // stores in Java the native Visualizer object
54 jfieldID fidJniData; // stores in Java additional resources used by the native Visualizer
Jean-Michel Trivibadca262013-09-20 10:48:55 -070055 jfieldID fidPeak; // to access Visualizer.MeasurementPeakRms.mPeak
56 jfieldID fidRms; // to access Visualizer.MeasurementPeakRms.mRms
Eric Laurentdf9b81c2010-07-02 08:12:41 -070057};
58static fields_t fields;
59
60struct visualizer_callback_cookie {
61 jclass visualizer_class; // Visualizer class
62 jobject visualizer_ref; // Visualizer object instance
John Grossman449725f2012-01-10 12:17:03 -080063
64 // Lazily allocated arrays used to hold callback data provided to java
65 // applications. These arrays are allocated during the first callback and
66 // reallocated when the size of the callback data changes. Allocating on
67 // demand and saving the arrays means that applications cannot safely hold a
68 // reference to the provided data (they need to make a copy if they want to
69 // hold onto outside of the callback scope), but it avoids GC thrash caused
70 // by constantly allocating and releasing arrays to hold callback data.
71 Mutex callback_data_lock;
72 jbyteArray waveform_data;
73 jbyteArray fft_data;
74
75 visualizer_callback_cookie() {
76 waveform_data = NULL;
77 fft_data = NULL;
78 }
79
80 ~visualizer_callback_cookie() {
81 cleanupBuffers();
82 }
83
84 void cleanupBuffers() {
85 AutoMutex lock(&callback_data_lock);
86 if (waveform_data || fft_data) {
87 JNIEnv *env = AndroidRuntime::getJNIEnv();
88
89 if (waveform_data) {
90 env->DeleteGlobalRef(waveform_data);
91 waveform_data = NULL;
92 }
93
94 if (fft_data) {
95 env->DeleteGlobalRef(fft_data);
96 fft_data = NULL;
97 }
98 }
99 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700100 };
101
102// ----------------------------------------------------------------------------
103class visualizerJniStorage {
104 public:
105 visualizer_callback_cookie mCallbackData;
106
107 visualizerJniStorage() {
108 }
109
110 ~visualizerJniStorage() {
111 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700112};
113
114
115static jint translateError(int code) {
116 switch(code) {
117 case NO_ERROR:
118 return VISUALIZER_SUCCESS;
119 case ALREADY_EXISTS:
120 return VISUALIZER_ERROR_ALREADY_EXISTS;
121 case NO_INIT:
122 return VISUALIZER_ERROR_NO_INIT;
123 case BAD_VALUE:
124 return VISUALIZER_ERROR_BAD_VALUE;
125 case INVALID_OPERATION:
126 return VISUALIZER_ERROR_INVALID_OPERATION;
127 case NO_MEMORY:
128 return VISUALIZER_ERROR_NO_MEMORY;
129 case DEAD_OBJECT:
130 return VISUALIZER_ERROR_DEAD_OBJECT;
131 default:
132 return VISUALIZER_ERROR;
133 }
134}
135
136
137// ----------------------------------------------------------------------------
John Grossman449725f2012-01-10 12:17:03 -0800138static void ensureArraySize(JNIEnv *env, jbyteArray *array, uint32_t size) {
139 if (NULL != *array) {
140 uint32_t len = env->GetArrayLength(*array);
141 if (len == size)
142 return;
143
144 env->DeleteGlobalRef(*array);
145 *array = NULL;
146 }
147
148 jbyteArray localRef = env->NewByteArray(size);
149 if (NULL != localRef) {
150 // Promote to global ref.
151 *array = (jbyteArray)env->NewGlobalRef(localRef);
152
153 // Release our (now pointless) local ref.
154 env->DeleteLocalRef(localRef);
155 }
156}
157
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700158static void captureCallback(void* user,
159 uint32_t waveformSize,
160 uint8_t *waveform,
161 uint32_t fftSize,
162 uint8_t *fft,
163 uint32_t samplingrate) {
164
165 int arg1 = 0;
166 int arg2 = 0;
167 size_t size;
168
169 visualizer_callback_cookie *callbackInfo = (visualizer_callback_cookie *)user;
170 JNIEnv *env = AndroidRuntime::getJNIEnv();
Mike J. Chen67a12182013-04-26 12:34:52 -0700171
172 if (!user || !env) {
173 ALOGW("captureCallback error user %p, env %p", user, env);
174 return;
175 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700176
Steve Block71f2cf12011-10-20 11:56:00 +0100177 ALOGV("captureCallback: callbackInfo %p, visualizer_ref %p visualizer_class %p",
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700178 callbackInfo,
179 callbackInfo->visualizer_ref,
180 callbackInfo->visualizer_class);
181
Mike J. Chen67a12182013-04-26 12:34:52 -0700182 AutoMutex lock(&callbackInfo->callback_data_lock);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700183
184 if (waveformSize != 0 && waveform != NULL) {
John Grossman449725f2012-01-10 12:17:03 -0800185 jbyteArray jArray;
186
187 ensureArraySize(env, &callbackInfo->waveform_data, waveformSize);
188 jArray = callbackInfo->waveform_data;
189
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700190 if (jArray != NULL) {
191 jbyte *nArray = env->GetByteArrayElements(jArray, NULL);
192 memcpy(nArray, waveform, waveformSize);
193 env->ReleaseByteArrayElements(jArray, nArray, 0);
194 env->CallStaticVoidMethod(
195 callbackInfo->visualizer_class,
196 fields.midPostNativeEvent,
197 callbackInfo->visualizer_ref,
198 NATIVE_EVENT_PCM_CAPTURE,
199 samplingrate,
200 0,
201 jArray);
202 }
203 }
204
205 if (fftSize != 0 && fft != NULL) {
John Grossman449725f2012-01-10 12:17:03 -0800206 jbyteArray jArray;
207
208 ensureArraySize(env, &callbackInfo->fft_data, fftSize);
209 jArray = callbackInfo->fft_data;
210
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700211 if (jArray != NULL) {
212 jbyte *nArray = env->GetByteArrayElements(jArray, NULL);
213 memcpy(nArray, fft, fftSize);
214 env->ReleaseByteArrayElements(jArray, nArray, 0);
215 env->CallStaticVoidMethod(
216 callbackInfo->visualizer_class,
217 fields.midPostNativeEvent,
218 callbackInfo->visualizer_ref,
219 NATIVE_EVENT_FFT_CAPTURE,
220 samplingrate,
221 0,
222 jArray);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700223 }
224 }
225
226 if (env->ExceptionCheck()) {
227 env->ExceptionDescribe();
228 env->ExceptionClear();
229 }
230}
231
232static Visualizer *getVisualizer(JNIEnv* env, jobject thiz)
233{
Ashok Bhatea7861c2013-12-17 12:42:00 +0000234 Visualizer *v = (Visualizer *)env->GetLongField(
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700235 thiz, fields.fidNativeVisualizer);
236 if (v == NULL) {
237 jniThrowException(env, "java/lang/IllegalStateException",
238 "Unable to retrieve Visualizer pointer");
239 }
240 return v;
241}
242
243// ----------------------------------------------------------------------------
244// This function gets some field IDs, which in turn causes class initialization.
245// It is called from a static block in Visualizer, which won't run until the
246// first time an instance of this class is used.
247static void
248android_media_visualizer_native_init(JNIEnv *env)
249{
250
Steve Block71f2cf12011-10-20 11:56:00 +0100251 ALOGV("android_media_visualizer_native_init");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700252
253 fields.clazzEffect = NULL;
254
255 // Get the Visualizer class
256 jclass clazz = env->FindClass(kClassPathName);
257 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000258 ALOGE("Can't find %s", kClassPathName);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700259 return;
260 }
261
262 fields.clazzEffect = (jclass)env->NewGlobalRef(clazz);
263
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700264 // Get the Visualizer.MeasurementPeakRms class
265 clazz = env->FindClass(kClassPeakRmsPathName);
266 if (clazz == NULL) {
267 ALOGE("Can't find %s", kClassPeakRmsPathName);
268 return;
269 }
270 jclass clazzMeasurementPeakRms = (jclass)env->NewGlobalRef(clazz);
271
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700272 // Get the postEvent method
273 fields.midPostNativeEvent = env->GetStaticMethodID(
274 fields.clazzEffect,
275 "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V");
276 if (fields.midPostNativeEvent == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000277 ALOGE("Can't find Visualizer.%s", "postEventFromNative");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700278 return;
279 }
280
281 // Get the variables fields
282 // nativeTrackInJavaObj
283 fields.fidNativeVisualizer = env->GetFieldID(
284 fields.clazzEffect,
Ashok Bhatea7861c2013-12-17 12:42:00 +0000285 "mNativeVisualizer", "J");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700286 if (fields.fidNativeVisualizer == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000287 ALOGE("Can't find Visualizer.%s", "mNativeVisualizer");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700288 return;
289 }
290 // fidJniData;
291 fields.fidJniData = env->GetFieldID(
292 fields.clazzEffect,
Ashok Bhatea7861c2013-12-17 12:42:00 +0000293 "mJniData", "J");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700294 if (fields.fidJniData == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000295 ALOGE("Can't find Visualizer.%s", "mJniData");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700296 return;
297 }
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700298 // fidPeak
299 fields.fidPeak = env->GetFieldID(
300 clazzMeasurementPeakRms,
301 "mPeak", "I");
302 if (fields.fidPeak == NULL) {
303 ALOGE("Can't find Visualizer.MeasurementPeakRms.%s", "mPeak");
304 return;
305 }
306 // fidRms
307 fields.fidRms = env->GetFieldID(
308 clazzMeasurementPeakRms,
309 "mRms", "I");
310 if (fields.fidRms == NULL) {
311 ALOGE("Can't find Visualizer.MeasurementPeakRms.%s", "mPeak");
312 return;
313 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700314
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700315 env->DeleteGlobalRef(clazzMeasurementPeakRms);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700316}
317
John Grossman3540a012012-01-11 12:23:42 -0800318static void android_media_visualizer_effect_callback(int32_t event,
319 void *user,
320 void *info) {
321 if ((event == AudioEffect::EVENT_ERROR) &&
322 (*((status_t*)info) == DEAD_OBJECT)) {
323 visualizerJniStorage* lpJniStorage = (visualizerJniStorage*)user;
324 visualizer_callback_cookie* callbackInfo = &lpJniStorage->mCallbackData;
325 JNIEnv *env = AndroidRuntime::getJNIEnv();
326
327 env->CallStaticVoidMethod(
328 callbackInfo->visualizer_class,
329 fields.midPostNativeEvent,
330 callbackInfo->visualizer_ref,
331 NATIVE_EVENT_SERVER_DIED,
332 0, 0, 0);
333 }
334}
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700335
336static jint
337android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
338 jint sessionId, jintArray jId)
339{
Steve Block71f2cf12011-10-20 11:56:00 +0100340 ALOGV("android_media_visualizer_native_setup");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700341 visualizerJniStorage* lpJniStorage = NULL;
342 int lStatus = VISUALIZER_ERROR_NO_MEMORY;
343 Visualizer* lpVisualizer = NULL;
344 jint* nId = NULL;
345
346 lpJniStorage = new visualizerJniStorage();
347 if (lpJniStorage == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000348 ALOGE("setup: Error creating JNI Storage");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700349 goto setup_failure;
350 }
351
352 lpJniStorage->mCallbackData.visualizer_class = (jclass)env->NewGlobalRef(fields.clazzEffect);
353 // we use a weak reference so the Visualizer object can be garbage collected.
354 lpJniStorage->mCallbackData.visualizer_ref = env->NewGlobalRef(weak_this);
355
Steve Block71f2cf12011-10-20 11:56:00 +0100356 ALOGV("setup: lpJniStorage: %p visualizer_ref %p visualizer_class %p, &mCallbackData %p",
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700357 lpJniStorage,
358 lpJniStorage->mCallbackData.visualizer_ref,
359 lpJniStorage->mCallbackData.visualizer_class,
360 &lpJniStorage->mCallbackData);
361
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700362 if (jId == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000363 ALOGE("setup: NULL java array for id pointer");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700364 lStatus = VISUALIZER_ERROR_BAD_VALUE;
365 goto setup_failure;
366 }
367
368 // create the native Visualizer object
369 lpVisualizer = new Visualizer(0,
John Grossman3540a012012-01-11 12:23:42 -0800370 android_media_visualizer_effect_callback,
371 lpJniStorage,
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700372 sessionId);
373 if (lpVisualizer == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000374 ALOGE("Error creating Visualizer");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700375 goto setup_failure;
376 }
377
378 lStatus = translateError(lpVisualizer->initCheck());
379 if (lStatus != VISUALIZER_SUCCESS && lStatus != VISUALIZER_ERROR_ALREADY_EXISTS) {
Steve Block3762c312012-01-06 19:20:56 +0000380 ALOGE("Visualizer initCheck failed %d", lStatus);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700381 goto setup_failure;
382 }
383
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700384 nId = (jint *) env->GetPrimitiveArrayCritical(jId, NULL);
385 if (nId == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000386 ALOGE("setup: Error retrieving id pointer");
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700387 lStatus = VISUALIZER_ERROR_BAD_VALUE;
388 goto setup_failure;
389 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700390 nId[0] = lpVisualizer->id();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700391 env->ReleasePrimitiveArrayCritical(jId, nId, 0);
392 nId = NULL;
393
Ashok Bhatea7861c2013-12-17 12:42:00 +0000394 env->SetLongField(thiz, fields.fidNativeVisualizer, (jlong)lpVisualizer);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700395
Ashok Bhatea7861c2013-12-17 12:42:00 +0000396 env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700397
398 return VISUALIZER_SUCCESS;
399
400 // failures:
401setup_failure:
402
403 if (nId != NULL) {
404 env->ReleasePrimitiveArrayCritical(jId, nId, 0);
405 }
406
407 if (lpVisualizer) {
408 delete lpVisualizer;
409 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000410 env->SetLongField(thiz, fields.fidNativeVisualizer, 0);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700411
412 if (lpJniStorage) {
413 delete lpJniStorage;
414 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000415 env->SetLongField(thiz, fields.fidJniData, 0);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700416
Ashok Bhatea7861c2013-12-17 12:42:00 +0000417 return (jint) lStatus;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700418}
419
420// ----------------------------------------------------------------------------
421static void android_media_visualizer_native_finalize(JNIEnv *env, jobject thiz) {
Ashok Bhatea7861c2013-12-17 12:42:00 +0000422 ALOGV("android_media_visualizer_native_finalize jobject: %p\n", thiz);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700423
424 // delete the Visualizer object
Ashok Bhatea7861c2013-12-17 12:42:00 +0000425 Visualizer* lpVisualizer = (Visualizer *)env->GetLongField(
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700426 thiz, fields.fidNativeVisualizer);
427 if (lpVisualizer) {
Ashok Bhatea7861c2013-12-17 12:42:00 +0000428 ALOGV("deleting Visualizer: %p\n", lpVisualizer);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700429 delete lpVisualizer;
430 }
431
432 // delete the JNI data
Ashok Bhatea7861c2013-12-17 12:42:00 +0000433 visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700434 thiz, fields.fidJniData);
435 if (lpJniStorage) {
Ashok Bhatea7861c2013-12-17 12:42:00 +0000436 ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700437 delete lpJniStorage;
438 }
439}
440
441// ----------------------------------------------------------------------------
442static void android_media_visualizer_native_release(JNIEnv *env, jobject thiz) {
443
444 // do everything a call to finalize would
445 android_media_visualizer_native_finalize(env, thiz);
446 // + reset the native resources in the Java object so any attempt to access
447 // them after a call to release fails.
Ashok Bhatea7861c2013-12-17 12:42:00 +0000448 env->SetLongField(thiz, fields.fidNativeVisualizer, 0);
449 env->SetLongField(thiz, fields.fidJniData, 0);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700450}
451
452static jint
453android_media_visualizer_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
454{
455 Visualizer* lpVisualizer = getVisualizer(env, thiz);
456 if (lpVisualizer == NULL) {
457 return VISUALIZER_ERROR_NO_INIT;
458 }
459
John Grossman449725f2012-01-10 12:17:03 -0800460 jint retVal = translateError(lpVisualizer->setEnabled(enabled));
461
462 if (!enabled) {
Ashok Bhatea7861c2013-12-17 12:42:00 +0000463 visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(
John Grossman449725f2012-01-10 12:17:03 -0800464 thiz, fields.fidJniData);
465
466 if (NULL != lpJniStorage)
467 lpJniStorage->mCallbackData.cleanupBuffers();
468 }
469
470 return retVal;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700471}
472
473static jboolean
474android_media_visualizer_native_getEnabled(JNIEnv *env, jobject thiz)
475{
476 Visualizer* lpVisualizer = getVisualizer(env, thiz);
477 if (lpVisualizer == NULL) {
Ashok Bhatea7861c2013-12-17 12:42:00 +0000478 return JNI_FALSE;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700479 }
480
Ashok Bhatea7861c2013-12-17 12:42:00 +0000481 if (lpVisualizer->getEnabled()) {
482 return JNI_TRUE;
483 } else {
484 return JNI_FALSE;
485 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700486}
487
488static jintArray
489android_media_visualizer_native_getCaptureSizeRange(JNIEnv *env, jobject thiz)
490{
491 jintArray jRange = env->NewIntArray(2);
492 jint *nRange = env->GetIntArrayElements(jRange, NULL);
493 nRange[0] = Visualizer::getMinCaptureSize();
494 nRange[1] = Visualizer::getMaxCaptureSize();
Steve Block71f2cf12011-10-20 11:56:00 +0100495 ALOGV("getCaptureSizeRange() min %d max %d", nRange[0], nRange[1]);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700496 env->ReleaseIntArrayElements(jRange, nRange, 0);
497 return jRange;
498}
499
500static jint
501android_media_visualizer_native_getMaxCaptureRate(JNIEnv *env, jobject thiz)
502{
Ashok Bhatea7861c2013-12-17 12:42:00 +0000503 return (jint) Visualizer::getMaxCaptureRate();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700504}
505
506static jint
507android_media_visualizer_native_setCaptureSize(JNIEnv *env, jobject thiz, jint size)
508{
509 Visualizer* lpVisualizer = getVisualizer(env, thiz);
510 if (lpVisualizer == NULL) {
511 return VISUALIZER_ERROR_NO_INIT;
512 }
513
514 return translateError(lpVisualizer->setCaptureSize(size));
515}
516
517static jint
518android_media_visualizer_native_getCaptureSize(JNIEnv *env, jobject thiz)
519{
520 Visualizer* lpVisualizer = getVisualizer(env, thiz);
521 if (lpVisualizer == NULL) {
522 return -1;
523 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000524 return (jint) lpVisualizer->getCaptureSize();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700525}
526
527static jint
Jean-Michel Trivie1123e72012-04-15 17:22:01 -0700528android_media_visualizer_native_setScalingMode(JNIEnv *env, jobject thiz, jint mode)
529{
530 Visualizer* lpVisualizer = getVisualizer(env, thiz);
531 if (lpVisualizer == NULL) {
532 return VISUALIZER_ERROR_NO_INIT;
533 }
534
535 return translateError(lpVisualizer->setScalingMode(mode));
536}
537
538static jint
539android_media_visualizer_native_getScalingMode(JNIEnv *env, jobject thiz)
540{
541 Visualizer* lpVisualizer = getVisualizer(env, thiz);
542 if (lpVisualizer == NULL) {
543 return -1;
544 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000545 return (jint)lpVisualizer->getScalingMode();
Jean-Michel Trivie1123e72012-04-15 17:22:01 -0700546}
547
548static jint
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700549android_media_visualizer_native_setMeasurementMode(JNIEnv *env, jobject thiz, jint mode)
550{
551 Visualizer* lpVisualizer = getVisualizer(env, thiz);
552 if (lpVisualizer == NULL) {
553 return VISUALIZER_ERROR_NO_INIT;
554 }
555 return translateError(lpVisualizer->setMeasurementMode(mode));
556}
557
558static jint
559android_media_visualizer_native_getMeasurementMode(JNIEnv *env, jobject thiz)
560{
561 Visualizer* lpVisualizer = getVisualizer(env, thiz);
562 if (lpVisualizer == NULL) {
563 return MEASUREMENT_MODE_NONE;
564 }
565 return lpVisualizer->getMeasurementMode();
566}
567
568static jint
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700569android_media_visualizer_native_getSamplingRate(JNIEnv *env, jobject thiz)
570{
571 Visualizer* lpVisualizer = getVisualizer(env, thiz);
572 if (lpVisualizer == NULL) {
573 return -1;
574 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000575 return (jint) lpVisualizer->getSamplingRate();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700576}
577
578static jint
579android_media_visualizer_native_getWaveForm(JNIEnv *env, jobject thiz, jbyteArray jWaveform)
580{
581 Visualizer* lpVisualizer = getVisualizer(env, thiz);
582 if (lpVisualizer == NULL) {
583 return VISUALIZER_ERROR_NO_INIT;
584 }
585
586 jbyte* nWaveform = (jbyte *) env->GetPrimitiveArrayCritical(jWaveform, NULL);
587 if (nWaveform == NULL) {
588 return VISUALIZER_ERROR_NO_MEMORY;
589 }
590 jint status = translateError(lpVisualizer->getWaveForm((uint8_t *)nWaveform));
591
592 env->ReleasePrimitiveArrayCritical(jWaveform, nWaveform, 0);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700593 return status;
594}
595
596static jint
597android_media_visualizer_native_getFft(JNIEnv *env, jobject thiz, jbyteArray jFft)
598{
599 Visualizer* lpVisualizer = getVisualizer(env, thiz);
600 if (lpVisualizer == NULL) {
601 return VISUALIZER_ERROR_NO_INIT;
602 }
603
604 jbyte* nFft = (jbyte *) env->GetPrimitiveArrayCritical(jFft, NULL);
605 if (nFft == NULL) {
606 return VISUALIZER_ERROR_NO_MEMORY;
607 }
608 jint status = translateError(lpVisualizer->getFft((uint8_t *)nFft));
609
610 env->ReleasePrimitiveArrayCritical(jFft, nFft, 0);
611
612 return status;
613}
614
615static jint
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700616android_media_visualizer_native_getPeakRms(JNIEnv *env, jobject thiz, jobject jPeakRmsObj)
617{
618 Visualizer* lpVisualizer = getVisualizer(env, thiz);
619 if (lpVisualizer == NULL) {
620 return VISUALIZER_ERROR_NO_INIT;
621 }
622 int32_t measurements[2];
623 jint status = translateError(
624 lpVisualizer->getIntMeasurements(MEASUREMENT_MODE_PEAK_RMS,
625 2, measurements));
626 if (status == VISUALIZER_SUCCESS) {
627 // measurement worked, write the values to the java object
628 env->SetIntField(jPeakRmsObj, fields.fidPeak, measurements[MEASUREMENT_IDX_PEAK]);
629 env->SetIntField(jPeakRmsObj, fields.fidRms, measurements[MEASUREMENT_IDX_RMS]);
630 }
631 return status;
632}
633
634static jint
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700635android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean jWaveform, jboolean jFft)
636{
637 Visualizer* lpVisualizer = getVisualizer(env, thiz);
638 if (lpVisualizer == NULL) {
639 return VISUALIZER_ERROR_NO_INIT;
640 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000641 visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(thiz,
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700642 fields.fidJniData);
643 if (lpJniStorage == NULL) {
644 return VISUALIZER_ERROR_NO_INIT;
645 }
646
Steve Block71f2cf12011-10-20 11:56:00 +0100647 ALOGV("setPeriodicCapture: rate %d, jWaveform %d jFft %d",
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700648 rate,
649 jWaveform,
650 jFft);
651
652 uint32_t flags = Visualizer::CAPTURE_CALL_JAVA;
653 if (jWaveform) flags |= Visualizer::CAPTURE_WAVEFORM;
654 if (jFft) flags |= Visualizer::CAPTURE_FFT;
655 Visualizer::capture_cbk_t cbk = captureCallback;
656 if (!jWaveform && !jFft) cbk = NULL;
657
658 return translateError(lpVisualizer->setCaptureCallBack(cbk,
659 &lpJniStorage->mCallbackData,
660 flags,
661 rate));
662}
663
664// ----------------------------------------------------------------------------
665
666// Dalvik VM type signatures
667static JNINativeMethod gMethods[] = {
668 {"native_init", "()V", (void *)android_media_visualizer_native_init},
669 {"native_setup", "(Ljava/lang/Object;I[I)I",
670 (void *)android_media_visualizer_native_setup},
671 {"native_finalize", "()V", (void *)android_media_visualizer_native_finalize},
672 {"native_release", "()V", (void *)android_media_visualizer_native_release},
673 {"native_setEnabled", "(Z)I", (void *)android_media_visualizer_native_setEnabled},
674 {"native_getEnabled", "()Z", (void *)android_media_visualizer_native_getEnabled},
675 {"getCaptureSizeRange", "()[I", (void *)android_media_visualizer_native_getCaptureSizeRange},
676 {"getMaxCaptureRate", "()I", (void *)android_media_visualizer_native_getMaxCaptureRate},
677 {"native_setCaptureSize", "(I)I", (void *)android_media_visualizer_native_setCaptureSize},
678 {"native_getCaptureSize", "()I", (void *)android_media_visualizer_native_getCaptureSize},
Jean-Michel Trivie1123e72012-04-15 17:22:01 -0700679 {"native_setScalingMode", "(I)I", (void *)android_media_visualizer_native_setScalingMode},
680 {"native_getScalingMode", "()I", (void *)android_media_visualizer_native_getScalingMode},
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700681 {"native_setMeasurementMode","(I)I", (void *)android_media_visualizer_native_setMeasurementMode},
682 {"native_getMeasurementMode","()I", (void *)android_media_visualizer_native_getMeasurementMode},
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700683 {"native_getSamplingRate", "()I", (void *)android_media_visualizer_native_getSamplingRate},
684 {"native_getWaveForm", "([B)I", (void *)android_media_visualizer_native_getWaveForm},
685 {"native_getFft", "([B)I", (void *)android_media_visualizer_native_getFft},
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700686 {"native_getPeakRms", "(Landroid/media/audiofx/Visualizer$MeasurementPeakRms;)I",
687 (void *)android_media_visualizer_native_getPeakRms},
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700688 {"native_setPeriodicCapture","(IZZ)I",(void *)android_media_setPeriodicCapture},
689};
690
691// ----------------------------------------------------------------------------
692
693int register_android_media_visualizer(JNIEnv *env)
694{
695 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
696}
697