blob: ce886eeb5f93b4df135ebf3dd632fa05a9d54add [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
Svet Ganovfa5ecdc2015-04-28 12:03:28 -070029#include <ScopedUtfChars.h>
30
Eric Laurentdf9b81c2010-07-02 08:12:41 -070031using namespace android;
32
33#define VISUALIZER_SUCCESS 0
Chih-Hung Hsieh0ca16ef2016-05-19 15:14:54 -070034#define VISUALIZER_ERROR (-1)
35#define VISUALIZER_ERROR_ALREADY_EXISTS (-2)
36#define VISUALIZER_ERROR_NO_INIT (-3)
37#define VISUALIZER_ERROR_BAD_VALUE (-4)
38#define VISUALIZER_ERROR_INVALID_OPERATION (-5)
39#define VISUALIZER_ERROR_NO_MEMORY (-6)
40#define VISUALIZER_ERROR_DEAD_OBJECT (-7)
Eric Laurentdf9b81c2010-07-02 08:12:41 -070041
42#define NATIVE_EVENT_PCM_CAPTURE 0
43#define NATIVE_EVENT_FFT_CAPTURE 1
John Grossman3540a012012-01-11 12:23:42 -080044#define NATIVE_EVENT_SERVER_DIED 2
Eric Laurentdf9b81c2010-07-02 08:12:41 -070045
46// ----------------------------------------------------------------------------
Eric Laurent1a5149e2010-09-21 18:18:20 -070047static const char* const kClassPathName = "android/media/audiofx/Visualizer";
Jean-Michel Trivibadca262013-09-20 10:48:55 -070048static const char* const kClassPeakRmsPathName =
49 "android/media/audiofx/Visualizer$MeasurementPeakRms";
Eric Laurentdf9b81c2010-07-02 08:12:41 -070050
51struct fields_t {
52 // these fields provide access from C++ to the...
53 jclass clazzEffect; // Visualizer class
54 jmethodID midPostNativeEvent; // event post callback method
55 jfieldID fidNativeVisualizer; // stores in Java the native Visualizer object
56 jfieldID fidJniData; // stores in Java additional resources used by the native Visualizer
Jean-Michel Trivibadca262013-09-20 10:48:55 -070057 jfieldID fidPeak; // to access Visualizer.MeasurementPeakRms.mPeak
58 jfieldID fidRms; // to access Visualizer.MeasurementPeakRms.mRms
Eric Laurentdf9b81c2010-07-02 08:12:41 -070059};
60static fields_t fields;
61
62struct visualizer_callback_cookie {
63 jclass visualizer_class; // Visualizer class
64 jobject visualizer_ref; // Visualizer object instance
John Grossman449725f2012-01-10 12:17:03 -080065
66 // Lazily allocated arrays used to hold callback data provided to java
67 // applications. These arrays are allocated during the first callback and
68 // reallocated when the size of the callback data changes. Allocating on
69 // demand and saving the arrays means that applications cannot safely hold a
70 // reference to the provided data (they need to make a copy if they want to
71 // hold onto outside of the callback scope), but it avoids GC thrash caused
72 // by constantly allocating and releasing arrays to hold callback data.
73 Mutex callback_data_lock;
74 jbyteArray waveform_data;
75 jbyteArray fft_data;
76
77 visualizer_callback_cookie() {
78 waveform_data = NULL;
79 fft_data = NULL;
80 }
81
82 ~visualizer_callback_cookie() {
83 cleanupBuffers();
84 }
85
86 void cleanupBuffers() {
87 AutoMutex lock(&callback_data_lock);
88 if (waveform_data || fft_data) {
89 JNIEnv *env = AndroidRuntime::getJNIEnv();
90
91 if (waveform_data) {
92 env->DeleteGlobalRef(waveform_data);
93 waveform_data = NULL;
94 }
95
96 if (fft_data) {
97 env->DeleteGlobalRef(fft_data);
98 fft_data = NULL;
99 }
100 }
101 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700102 };
103
104// ----------------------------------------------------------------------------
Eric Laurent76f81332015-06-04 16:20:47 -0700105class VisualizerJniStorage {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700106 public:
107 visualizer_callback_cookie mCallbackData;
108
Eric Laurent76f81332015-06-04 16:20:47 -0700109 VisualizerJniStorage() {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700110 }
111
Eric Laurent76f81332015-06-04 16:20:47 -0700112 ~VisualizerJniStorage() {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700113 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700114};
115
116
117static jint translateError(int code) {
118 switch(code) {
119 case NO_ERROR:
120 return VISUALIZER_SUCCESS;
121 case ALREADY_EXISTS:
122 return VISUALIZER_ERROR_ALREADY_EXISTS;
123 case NO_INIT:
124 return VISUALIZER_ERROR_NO_INIT;
125 case BAD_VALUE:
126 return VISUALIZER_ERROR_BAD_VALUE;
127 case INVALID_OPERATION:
128 return VISUALIZER_ERROR_INVALID_OPERATION;
129 case NO_MEMORY:
130 return VISUALIZER_ERROR_NO_MEMORY;
131 case DEAD_OBJECT:
132 return VISUALIZER_ERROR_DEAD_OBJECT;
133 default:
134 return VISUALIZER_ERROR;
135 }
136}
137
Eric Laurent76f81332015-06-04 16:20:47 -0700138static Mutex sLock;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700139
140// ----------------------------------------------------------------------------
John Grossman449725f2012-01-10 12:17:03 -0800141static void ensureArraySize(JNIEnv *env, jbyteArray *array, uint32_t size) {
142 if (NULL != *array) {
143 uint32_t len = env->GetArrayLength(*array);
144 if (len == size)
145 return;
146
147 env->DeleteGlobalRef(*array);
148 *array = NULL;
149 }
150
151 jbyteArray localRef = env->NewByteArray(size);
152 if (NULL != localRef) {
153 // Promote to global ref.
154 *array = (jbyteArray)env->NewGlobalRef(localRef);
155
156 // Release our (now pointless) local ref.
157 env->DeleteLocalRef(localRef);
158 }
159}
160
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700161static void captureCallback(void* user,
162 uint32_t waveformSize,
163 uint8_t *waveform,
164 uint32_t fftSize,
165 uint8_t *fft,
166 uint32_t samplingrate) {
167
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700168 visualizer_callback_cookie *callbackInfo = (visualizer_callback_cookie *)user;
169 JNIEnv *env = AndroidRuntime::getJNIEnv();
Mike J. Chen67a12182013-04-26 12:34:52 -0700170
171 if (!user || !env) {
172 ALOGW("captureCallback error user %p, env %p", user, env);
173 return;
174 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700175
Steve Block71f2cf12011-10-20 11:56:00 +0100176 ALOGV("captureCallback: callbackInfo %p, visualizer_ref %p visualizer_class %p",
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700177 callbackInfo,
178 callbackInfo->visualizer_ref,
179 callbackInfo->visualizer_class);
180
Mike J. Chen67a12182013-04-26 12:34:52 -0700181 AutoMutex lock(&callbackInfo->callback_data_lock);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700182
183 if (waveformSize != 0 && waveform != NULL) {
John Grossman449725f2012-01-10 12:17:03 -0800184 jbyteArray jArray;
185
186 ensureArraySize(env, &callbackInfo->waveform_data, waveformSize);
187 jArray = callbackInfo->waveform_data;
188
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700189 if (jArray != NULL) {
190 jbyte *nArray = env->GetByteArrayElements(jArray, NULL);
191 memcpy(nArray, waveform, waveformSize);
192 env->ReleaseByteArrayElements(jArray, nArray, 0);
193 env->CallStaticVoidMethod(
194 callbackInfo->visualizer_class,
195 fields.midPostNativeEvent,
196 callbackInfo->visualizer_ref,
197 NATIVE_EVENT_PCM_CAPTURE,
198 samplingrate,
199 0,
200 jArray);
201 }
202 }
203
204 if (fftSize != 0 && fft != NULL) {
John Grossman449725f2012-01-10 12:17:03 -0800205 jbyteArray jArray;
206
207 ensureArraySize(env, &callbackInfo->fft_data, fftSize);
208 jArray = callbackInfo->fft_data;
209
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700210 if (jArray != NULL) {
211 jbyte *nArray = env->GetByteArrayElements(jArray, NULL);
212 memcpy(nArray, fft, fftSize);
213 env->ReleaseByteArrayElements(jArray, nArray, 0);
214 env->CallStaticVoidMethod(
215 callbackInfo->visualizer_class,
216 fields.midPostNativeEvent,
217 callbackInfo->visualizer_ref,
218 NATIVE_EVENT_FFT_CAPTURE,
219 samplingrate,
220 0,
221 jArray);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700222 }
223 }
224
225 if (env->ExceptionCheck()) {
226 env->ExceptionDescribe();
227 env->ExceptionClear();
228 }
229}
230
Eric Laurent76f81332015-06-04 16:20:47 -0700231// ----------------------------------------------------------------------------
232
233static sp<Visualizer> getVisualizer(JNIEnv* env, jobject thiz)
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700234{
Eric Laurent76f81332015-06-04 16:20:47 -0700235 Mutex::Autolock l(sLock);
236 Visualizer* const v =
237 (Visualizer*)env->GetLongField(thiz, fields.fidNativeVisualizer);
238 return sp<Visualizer>(v);
239}
240
241static sp<Visualizer> setVisualizer(JNIEnv* env, jobject thiz,
242 const sp<Visualizer>& v)
243{
244 Mutex::Autolock l(sLock);
245 sp<Visualizer> old =
246 (Visualizer*)env->GetLongField(thiz, fields.fidNativeVisualizer);
247 if (v.get()) {
248 v->incStrong((void*)setVisualizer);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700249 }
Eric Laurent76f81332015-06-04 16:20:47 -0700250 if (old != 0) {
251 old->decStrong((void*)setVisualizer);
252 }
253 env->SetLongField(thiz, fields.fidNativeVisualizer, (jlong)v.get());
254 return old;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700255}
256
257// ----------------------------------------------------------------------------
258// This function gets some field IDs, which in turn causes class initialization.
259// It is called from a static block in Visualizer, which won't run until the
260// first time an instance of this class is used.
261static void
262android_media_visualizer_native_init(JNIEnv *env)
263{
264
Steve Block71f2cf12011-10-20 11:56:00 +0100265 ALOGV("android_media_visualizer_native_init");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700266
267 fields.clazzEffect = NULL;
268
269 // Get the Visualizer class
270 jclass clazz = env->FindClass(kClassPathName);
271 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000272 ALOGE("Can't find %s", kClassPathName);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700273 return;
274 }
275
276 fields.clazzEffect = (jclass)env->NewGlobalRef(clazz);
277
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700278 // Get the Visualizer.MeasurementPeakRms class
279 clazz = env->FindClass(kClassPeakRmsPathName);
280 if (clazz == NULL) {
281 ALOGE("Can't find %s", kClassPeakRmsPathName);
282 return;
283 }
284 jclass clazzMeasurementPeakRms = (jclass)env->NewGlobalRef(clazz);
285
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700286 // Get the postEvent method
287 fields.midPostNativeEvent = env->GetStaticMethodID(
288 fields.clazzEffect,
289 "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V");
290 if (fields.midPostNativeEvent == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000291 ALOGE("Can't find Visualizer.%s", "postEventFromNative");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700292 return;
293 }
294
295 // Get the variables fields
296 // nativeTrackInJavaObj
297 fields.fidNativeVisualizer = env->GetFieldID(
298 fields.clazzEffect,
Ashok Bhatea7861c2013-12-17 12:42:00 +0000299 "mNativeVisualizer", "J");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700300 if (fields.fidNativeVisualizer == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000301 ALOGE("Can't find Visualizer.%s", "mNativeVisualizer");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700302 return;
303 }
304 // fidJniData;
305 fields.fidJniData = env->GetFieldID(
306 fields.clazzEffect,
Ashok Bhatea7861c2013-12-17 12:42:00 +0000307 "mJniData", "J");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700308 if (fields.fidJniData == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000309 ALOGE("Can't find Visualizer.%s", "mJniData");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700310 return;
311 }
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700312 // fidPeak
313 fields.fidPeak = env->GetFieldID(
314 clazzMeasurementPeakRms,
315 "mPeak", "I");
316 if (fields.fidPeak == NULL) {
317 ALOGE("Can't find Visualizer.MeasurementPeakRms.%s", "mPeak");
318 return;
319 }
320 // fidRms
321 fields.fidRms = env->GetFieldID(
322 clazzMeasurementPeakRms,
323 "mRms", "I");
324 if (fields.fidRms == NULL) {
325 ALOGE("Can't find Visualizer.MeasurementPeakRms.%s", "mPeak");
326 return;
327 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700328
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700329 env->DeleteGlobalRef(clazzMeasurementPeakRms);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700330}
331
John Grossman3540a012012-01-11 12:23:42 -0800332static void android_media_visualizer_effect_callback(int32_t event,
333 void *user,
334 void *info) {
335 if ((event == AudioEffect::EVENT_ERROR) &&
336 (*((status_t*)info) == DEAD_OBJECT)) {
Eric Laurent76f81332015-06-04 16:20:47 -0700337 VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage*)user;
John Grossman3540a012012-01-11 12:23:42 -0800338 visualizer_callback_cookie* callbackInfo = &lpJniStorage->mCallbackData;
339 JNIEnv *env = AndroidRuntime::getJNIEnv();
340
341 env->CallStaticVoidMethod(
342 callbackInfo->visualizer_class,
343 fields.midPostNativeEvent,
344 callbackInfo->visualizer_ref,
345 NATIVE_EVENT_SERVER_DIED,
Haitao Feng8bd6a202014-12-31 13:48:08 +0800346 0, 0, NULL);
John Grossman3540a012012-01-11 12:23:42 -0800347 }
348}
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700349
350static jint
351android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
Svet Ganovfa5ecdc2015-04-28 12:03:28 -0700352 jint sessionId, jintArray jId, jstring opPackageName)
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700353{
Steve Block71f2cf12011-10-20 11:56:00 +0100354 ALOGV("android_media_visualizer_native_setup");
Eric Laurent76f81332015-06-04 16:20:47 -0700355 VisualizerJniStorage* lpJniStorage = NULL;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700356 int lStatus = VISUALIZER_ERROR_NO_MEMORY;
Eric Laurent76f81332015-06-04 16:20:47 -0700357 sp<Visualizer> lpVisualizer;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700358 jint* nId = NULL;
359
Svet Ganovfa5ecdc2015-04-28 12:03:28 -0700360 ScopedUtfChars opPackageNameStr(env, opPackageName);
361
Eric Laurent76f81332015-06-04 16:20:47 -0700362 setVisualizer(env, thiz, 0);
363
364 lpJniStorage = new VisualizerJniStorage();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700365 if (lpJniStorage == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000366 ALOGE("setup: Error creating JNI Storage");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700367 goto setup_failure;
368 }
369
370 lpJniStorage->mCallbackData.visualizer_class = (jclass)env->NewGlobalRef(fields.clazzEffect);
371 // we use a weak reference so the Visualizer object can be garbage collected.
372 lpJniStorage->mCallbackData.visualizer_ref = env->NewGlobalRef(weak_this);
373
Steve Block71f2cf12011-10-20 11:56:00 +0100374 ALOGV("setup: lpJniStorage: %p visualizer_ref %p visualizer_class %p, &mCallbackData %p",
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700375 lpJniStorage,
376 lpJniStorage->mCallbackData.visualizer_ref,
377 lpJniStorage->mCallbackData.visualizer_class,
378 &lpJniStorage->mCallbackData);
379
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700380 if (jId == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000381 ALOGE("setup: NULL java array for id pointer");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700382 lStatus = VISUALIZER_ERROR_BAD_VALUE;
383 goto setup_failure;
384 }
385
386 // create the native Visualizer object
Svet Ganovfa5ecdc2015-04-28 12:03:28 -0700387 lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()),
388 0,
John Grossman3540a012012-01-11 12:23:42 -0800389 android_media_visualizer_effect_callback,
390 lpJniStorage,
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700391 sessionId);
Eric Laurent76f81332015-06-04 16:20:47 -0700392 if (lpVisualizer == 0) {
Steve Block3762c312012-01-06 19:20:56 +0000393 ALOGE("Error creating Visualizer");
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700394 goto setup_failure;
395 }
396
397 lStatus = translateError(lpVisualizer->initCheck());
398 if (lStatus != VISUALIZER_SUCCESS && lStatus != VISUALIZER_ERROR_ALREADY_EXISTS) {
Steve Block3762c312012-01-06 19:20:56 +0000399 ALOGE("Visualizer initCheck failed %d", lStatus);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700400 goto setup_failure;
401 }
402
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700403 nId = (jint *) env->GetPrimitiveArrayCritical(jId, NULL);
404 if (nId == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000405 ALOGE("setup: Error retrieving id pointer");
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700406 lStatus = VISUALIZER_ERROR_BAD_VALUE;
407 goto setup_failure;
408 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700409 nId[0] = lpVisualizer->id();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700410 env->ReleasePrimitiveArrayCritical(jId, nId, 0);
411 nId = NULL;
412
Eric Laurent76f81332015-06-04 16:20:47 -0700413 setVisualizer(env, thiz, lpVisualizer);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700414
Ashok Bhatea7861c2013-12-17 12:42:00 +0000415 env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700416
417 return VISUALIZER_SUCCESS;
418
419 // failures:
420setup_failure:
421
422 if (nId != NULL) {
423 env->ReleasePrimitiveArrayCritical(jId, nId, 0);
424 }
425
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700426 if (lpJniStorage) {
Eric Laurent76f81332015-06-04 16:20:47 -0700427 env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_class);
428 env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_ref);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700429 delete lpJniStorage;
430 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000431 env->SetLongField(thiz, fields.fidJniData, 0);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700432
Ashok Bhatea7861c2013-12-17 12:42:00 +0000433 return (jint) lStatus;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700434}
435
436// ----------------------------------------------------------------------------
Eric Laurent76f81332015-06-04 16:20:47 -0700437static void android_media_visualizer_native_release(JNIEnv *env, jobject thiz) {
438 sp<Visualizer> lpVisualizer = setVisualizer(env, thiz, 0);
439 if (lpVisualizer == 0) {
440 return;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700441 }
442
443 // delete the JNI data
Eric Laurent76f81332015-06-04 16:20:47 -0700444 VisualizerJniStorage* lpJniStorage =
445 (VisualizerJniStorage *)env->GetLongField(thiz, fields.fidJniData);
446
447 // reset the native resources in the Java object so any attempt to access
448 // them after a call to release fails.
449 env->SetLongField(thiz, fields.fidJniData, 0);
450
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700451 if (lpJniStorage) {
Ashok Bhatea7861c2013-12-17 12:42:00 +0000452 ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
Eric Laurent07799982015-06-19 09:13:02 -0700453 env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_class);
454 env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_ref);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700455 delete lpJniStorage;
456 }
457}
458
Eric Laurent76f81332015-06-04 16:20:47 -0700459static void android_media_visualizer_native_finalize(JNIEnv *env, jobject thiz) {
460 ALOGV("android_media_visualizer_native_finalize jobject: %p\n", thiz);
461 android_media_visualizer_native_release(env, thiz);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700462}
463
Eric Laurent76f81332015-06-04 16:20:47 -0700464// ----------------------------------------------------------------------------
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700465static jint
466android_media_visualizer_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
467{
Eric Laurent76f81332015-06-04 16:20:47 -0700468 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
469 if (lpVisualizer == 0) {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700470 return VISUALIZER_ERROR_NO_INIT;
471 }
472
John Grossman449725f2012-01-10 12:17:03 -0800473 jint retVal = translateError(lpVisualizer->setEnabled(enabled));
474
475 if (!enabled) {
Eric Laurent76f81332015-06-04 16:20:47 -0700476 VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage *)env->GetLongField(
John Grossman449725f2012-01-10 12:17:03 -0800477 thiz, fields.fidJniData);
478
479 if (NULL != lpJniStorage)
480 lpJniStorage->mCallbackData.cleanupBuffers();
481 }
482
483 return retVal;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700484}
485
486static jboolean
487android_media_visualizer_native_getEnabled(JNIEnv *env, jobject thiz)
488{
Eric Laurent76f81332015-06-04 16:20:47 -0700489 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
490 if (lpVisualizer == 0) {
Ashok Bhatea7861c2013-12-17 12:42:00 +0000491 return JNI_FALSE;
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700492 }
493
Ashok Bhatea7861c2013-12-17 12:42:00 +0000494 if (lpVisualizer->getEnabled()) {
495 return JNI_TRUE;
496 } else {
497 return JNI_FALSE;
498 }
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700499}
500
501static jintArray
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800502android_media_visualizer_native_getCaptureSizeRange(JNIEnv *env, jobject /* thiz */)
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700503{
504 jintArray jRange = env->NewIntArray(2);
505 jint *nRange = env->GetIntArrayElements(jRange, NULL);
506 nRange[0] = Visualizer::getMinCaptureSize();
507 nRange[1] = Visualizer::getMaxCaptureSize();
Steve Block71f2cf12011-10-20 11:56:00 +0100508 ALOGV("getCaptureSizeRange() min %d max %d", nRange[0], nRange[1]);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700509 env->ReleaseIntArrayElements(jRange, nRange, 0);
510 return jRange;
511}
512
513static jint
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800514android_media_visualizer_native_getMaxCaptureRate(JNIEnv* /* env */, jobject /* thiz */)
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700515{
Ashok Bhatea7861c2013-12-17 12:42:00 +0000516 return (jint) Visualizer::getMaxCaptureRate();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700517}
518
519static jint
520android_media_visualizer_native_setCaptureSize(JNIEnv *env, jobject thiz, jint size)
521{
Eric Laurent76f81332015-06-04 16:20:47 -0700522 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
523 if (lpVisualizer == 0) {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700524 return VISUALIZER_ERROR_NO_INIT;
525 }
526
527 return translateError(lpVisualizer->setCaptureSize(size));
528}
529
530static jint
531android_media_visualizer_native_getCaptureSize(JNIEnv *env, jobject thiz)
532{
Eric Laurent76f81332015-06-04 16:20:47 -0700533 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
534 if (lpVisualizer == 0) {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700535 return -1;
536 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000537 return (jint) lpVisualizer->getCaptureSize();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700538}
539
540static jint
Jean-Michel Trivie1123e72012-04-15 17:22:01 -0700541android_media_visualizer_native_setScalingMode(JNIEnv *env, jobject thiz, jint mode)
542{
Eric Laurent76f81332015-06-04 16:20:47 -0700543 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
544 if (lpVisualizer == 0) {
Jean-Michel Trivie1123e72012-04-15 17:22:01 -0700545 return VISUALIZER_ERROR_NO_INIT;
546 }
547
548 return translateError(lpVisualizer->setScalingMode(mode));
549}
550
551static jint
552android_media_visualizer_native_getScalingMode(JNIEnv *env, jobject thiz)
553{
Eric Laurent76f81332015-06-04 16:20:47 -0700554 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
555 if (lpVisualizer == 0) {
Jean-Michel Trivie1123e72012-04-15 17:22:01 -0700556 return -1;
557 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000558 return (jint)lpVisualizer->getScalingMode();
Jean-Michel Trivie1123e72012-04-15 17:22:01 -0700559}
560
561static jint
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700562android_media_visualizer_native_setMeasurementMode(JNIEnv *env, jobject thiz, jint mode)
563{
Eric Laurent76f81332015-06-04 16:20:47 -0700564 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
565 if (lpVisualizer == 0) {
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700566 return VISUALIZER_ERROR_NO_INIT;
567 }
568 return translateError(lpVisualizer->setMeasurementMode(mode));
569}
570
571static jint
572android_media_visualizer_native_getMeasurementMode(JNIEnv *env, jobject thiz)
573{
Eric Laurent76f81332015-06-04 16:20:47 -0700574 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
575 if (lpVisualizer == 0) {
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700576 return MEASUREMENT_MODE_NONE;
577 }
578 return lpVisualizer->getMeasurementMode();
579}
580
581static jint
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700582android_media_visualizer_native_getSamplingRate(JNIEnv *env, jobject thiz)
583{
Eric Laurent76f81332015-06-04 16:20:47 -0700584 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
585 if (lpVisualizer == 0) {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700586 return -1;
587 }
Ashok Bhatea7861c2013-12-17 12:42:00 +0000588 return (jint) lpVisualizer->getSamplingRate();
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700589}
590
591static jint
592android_media_visualizer_native_getWaveForm(JNIEnv *env, jobject thiz, jbyteArray jWaveform)
593{
Eric Laurent76f81332015-06-04 16:20:47 -0700594 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
595 if (lpVisualizer == 0) {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700596 return VISUALIZER_ERROR_NO_INIT;
597 }
598
599 jbyte* nWaveform = (jbyte *) env->GetPrimitiveArrayCritical(jWaveform, NULL);
600 if (nWaveform == NULL) {
601 return VISUALIZER_ERROR_NO_MEMORY;
602 }
603 jint status = translateError(lpVisualizer->getWaveForm((uint8_t *)nWaveform));
604
605 env->ReleasePrimitiveArrayCritical(jWaveform, nWaveform, 0);
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700606 return status;
607}
608
609static jint
610android_media_visualizer_native_getFft(JNIEnv *env, jobject thiz, jbyteArray jFft)
611{
Eric Laurent76f81332015-06-04 16:20:47 -0700612 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
613 if (lpVisualizer == 0) {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700614 return VISUALIZER_ERROR_NO_INIT;
615 }
616
617 jbyte* nFft = (jbyte *) env->GetPrimitiveArrayCritical(jFft, NULL);
618 if (nFft == NULL) {
619 return VISUALIZER_ERROR_NO_MEMORY;
620 }
621 jint status = translateError(lpVisualizer->getFft((uint8_t *)nFft));
622
623 env->ReleasePrimitiveArrayCritical(jFft, nFft, 0);
624
625 return status;
626}
627
628static jint
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700629android_media_visualizer_native_getPeakRms(JNIEnv *env, jobject thiz, jobject jPeakRmsObj)
630{
Eric Laurent76f81332015-06-04 16:20:47 -0700631 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
632 if (lpVisualizer == 0) {
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700633 return VISUALIZER_ERROR_NO_INIT;
634 }
635 int32_t measurements[2];
636 jint status = translateError(
637 lpVisualizer->getIntMeasurements(MEASUREMENT_MODE_PEAK_RMS,
638 2, measurements));
639 if (status == VISUALIZER_SUCCESS) {
640 // measurement worked, write the values to the java object
641 env->SetIntField(jPeakRmsObj, fields.fidPeak, measurements[MEASUREMENT_IDX_PEAK]);
642 env->SetIntField(jPeakRmsObj, fields.fidRms, measurements[MEASUREMENT_IDX_RMS]);
643 }
644 return status;
645}
646
647static jint
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700648android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean jWaveform, jboolean jFft)
649{
Eric Laurent76f81332015-06-04 16:20:47 -0700650 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz);
651 if (lpVisualizer == 0) {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700652 return VISUALIZER_ERROR_NO_INIT;
653 }
Eric Laurent76f81332015-06-04 16:20:47 -0700654 VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage *)env->GetLongField(thiz,
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700655 fields.fidJniData);
656 if (lpJniStorage == NULL) {
657 return VISUALIZER_ERROR_NO_INIT;
658 }
659
Steve Block71f2cf12011-10-20 11:56:00 +0100660 ALOGV("setPeriodicCapture: rate %d, jWaveform %d jFft %d",
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700661 rate,
662 jWaveform,
663 jFft);
664
665 uint32_t flags = Visualizer::CAPTURE_CALL_JAVA;
666 if (jWaveform) flags |= Visualizer::CAPTURE_WAVEFORM;
667 if (jFft) flags |= Visualizer::CAPTURE_FFT;
668 Visualizer::capture_cbk_t cbk = captureCallback;
669 if (!jWaveform && !jFft) cbk = NULL;
670
671 return translateError(lpVisualizer->setCaptureCallBack(cbk,
672 &lpJniStorage->mCallbackData,
673 flags,
674 rate));
675}
676
677// ----------------------------------------------------------------------------
678
679// Dalvik VM type signatures
Daniel Micay76f6a862015-09-19 17:31:01 -0400680static const JNINativeMethod gMethods[] = {
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700681 {"native_init", "()V", (void *)android_media_visualizer_native_init},
Svet Ganovfa5ecdc2015-04-28 12:03:28 -0700682 {"native_setup", "(Ljava/lang/Object;I[ILjava/lang/String;)I",
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700683 (void *)android_media_visualizer_native_setup},
684 {"native_finalize", "()V", (void *)android_media_visualizer_native_finalize},
685 {"native_release", "()V", (void *)android_media_visualizer_native_release},
686 {"native_setEnabled", "(Z)I", (void *)android_media_visualizer_native_setEnabled},
687 {"native_getEnabled", "()Z", (void *)android_media_visualizer_native_getEnabled},
688 {"getCaptureSizeRange", "()[I", (void *)android_media_visualizer_native_getCaptureSizeRange},
689 {"getMaxCaptureRate", "()I", (void *)android_media_visualizer_native_getMaxCaptureRate},
690 {"native_setCaptureSize", "(I)I", (void *)android_media_visualizer_native_setCaptureSize},
691 {"native_getCaptureSize", "()I", (void *)android_media_visualizer_native_getCaptureSize},
Jean-Michel Trivie1123e72012-04-15 17:22:01 -0700692 {"native_setScalingMode", "(I)I", (void *)android_media_visualizer_native_setScalingMode},
693 {"native_getScalingMode", "()I", (void *)android_media_visualizer_native_getScalingMode},
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700694 {"native_setMeasurementMode","(I)I", (void *)android_media_visualizer_native_setMeasurementMode},
695 {"native_getMeasurementMode","()I", (void *)android_media_visualizer_native_getMeasurementMode},
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700696 {"native_getSamplingRate", "()I", (void *)android_media_visualizer_native_getSamplingRate},
697 {"native_getWaveForm", "([B)I", (void *)android_media_visualizer_native_getWaveForm},
698 {"native_getFft", "([B)I", (void *)android_media_visualizer_native_getFft},
Jean-Michel Trivibadca262013-09-20 10:48:55 -0700699 {"native_getPeakRms", "(Landroid/media/audiofx/Visualizer$MeasurementPeakRms;)I",
700 (void *)android_media_visualizer_native_getPeakRms},
Eric Laurentdf9b81c2010-07-02 08:12:41 -0700701 {"native_setPeriodicCapture","(IZZ)I",(void *)android_media_setPeriodicCapture},
702};
703
704// ----------------------------------------------------------------------------
705
706int register_android_media_visualizer(JNIEnv *env)
707{
708 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
709}
710