1 /* 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> 26 #include <utils/threads.h> 27 #include "media/Visualizer.h" 28 29 #include <ScopedUtfChars.h> 30 31 using namespace android; 32 33 #define VISUALIZER_SUCCESS 0 34 #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 41 42 #define NATIVE_EVENT_PCM_CAPTURE 0 43 #define NATIVE_EVENT_FFT_CAPTURE 1 44 #define NATIVE_EVENT_SERVER_DIED 2 45 46 // ---------------------------------------------------------------------------- 47 static const char* const kClassPathName = "android/media/audiofx/Visualizer"; 48 static const char* const kClassPeakRmsPathName = 49 "android/media/audiofx/Visualizer$MeasurementPeakRms"; 50 51 struct 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 57 jfieldID fidPeak; // to access Visualizer.MeasurementPeakRms.mPeak 58 jfieldID fidRms; // to access Visualizer.MeasurementPeakRms.mRms 59 }; 60 static fields_t fields; 61 62 struct visualizer_callback_cookie { 63 jclass visualizer_class; // Visualizer class 64 jobject visualizer_ref; // Visualizer object instance 65 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 } 102 }; 103 104 // ---------------------------------------------------------------------------- 105 class VisualizerJniStorage { 106 public: 107 visualizer_callback_cookie mCallbackData; 108 109 VisualizerJniStorage() { 110 } 111 112 ~VisualizerJniStorage() { 113 } 114 }; 115 116 117 static 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 138 static Mutex sLock; 139 140 // ---------------------------------------------------------------------------- 141 static 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 161 static 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 168 visualizer_callback_cookie *callbackInfo = (visualizer_callback_cookie *)user; 169 JNIEnv *env = AndroidRuntime::getJNIEnv(); 170 171 if (!user || !env) { 172 ALOGW("captureCallback error user %p, env %p", user, env); 173 return; 174 } 175 176 ALOGV("captureCallback: callbackInfo %p, visualizer_ref %p visualizer_class %p", 177 callbackInfo, 178 callbackInfo->visualizer_ref, 179 callbackInfo->visualizer_class); 180 181 AutoMutex lock(&callbackInfo->callback_data_lock); 182 183 if (waveformSize != 0 && waveform != NULL) { 184 jbyteArray jArray; 185 186 ensureArraySize(env, &callbackInfo->waveform_data, waveformSize); 187 jArray = callbackInfo->waveform_data; 188 189 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) { 205 jbyteArray jArray; 206 207 ensureArraySize(env, &callbackInfo->fft_data, fftSize); 208 jArray = callbackInfo->fft_data; 209 210 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); 222 } 223 } 224 225 if (env->ExceptionCheck()) { 226 env->ExceptionDescribe(); 227 env->ExceptionClear(); 228 } 229 } 230 231 // ---------------------------------------------------------------------------- 232 233 static sp<Visualizer> getVisualizer(JNIEnv* env, jobject thiz) 234 { 235 Mutex::Autolock l(sLock); 236 Visualizer* const v = 237 (Visualizer*)env->GetLongField(thiz, fields.fidNativeVisualizer); 238 return sp<Visualizer>(v); 239 } 240 241 static 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); 249 } 250 if (old != 0) { 251 old->decStrong((void*)setVisualizer); 252 } 253 env->SetLongField(thiz, fields.fidNativeVisualizer, (jlong)v.get()); 254 return old; 255 } 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. 261 static void 262 android_media_visualizer_native_init(JNIEnv *env) 263 { 264 265 ALOGV("android_media_visualizer_native_init"); 266 267 fields.clazzEffect = NULL; 268 269 // Get the Visualizer class 270 jclass clazz = env->FindClass(kClassPathName); 271 if (clazz == NULL) { 272 ALOGE("Can't find %s", kClassPathName); 273 return; 274 } 275 276 fields.clazzEffect = (jclass)env->NewGlobalRef(clazz); 277 278 // 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 286 // 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) { 291 ALOGE("Can't find Visualizer.%s", "postEventFromNative"); 292 return; 293 } 294 295 // Get the variables fields 296 // nativeTrackInJavaObj 297 fields.fidNativeVisualizer = env->GetFieldID( 298 fields.clazzEffect, 299 "mNativeVisualizer", "J"); 300 if (fields.fidNativeVisualizer == NULL) { 301 ALOGE("Can't find Visualizer.%s", "mNativeVisualizer"); 302 return; 303 } 304 // fidJniData; 305 fields.fidJniData = env->GetFieldID( 306 fields.clazzEffect, 307 "mJniData", "J"); 308 if (fields.fidJniData == NULL) { 309 ALOGE("Can't find Visualizer.%s", "mJniData"); 310 return; 311 } 312 // 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 } 328 329 env->DeleteGlobalRef(clazzMeasurementPeakRms); 330 } 331 332 static 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)) { 337 VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage*)user; 338 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, 346 0, 0, NULL); 347 } 348 } 349 350 static jint 351 android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, 352 jint sessionId, jintArray jId, jstring opPackageName) 353 { 354 ALOGV("android_media_visualizer_native_setup"); 355 VisualizerJniStorage* lpJniStorage = NULL; 356 int lStatus = VISUALIZER_ERROR_NO_MEMORY; 357 sp<Visualizer> lpVisualizer; 358 jint* nId = NULL; 359 360 ScopedUtfChars opPackageNameStr(env, opPackageName); 361 362 setVisualizer(env, thiz, 0); 363 364 lpJniStorage = new VisualizerJniStorage(); 365 if (lpJniStorage == NULL) { 366 ALOGE("setup: Error creating JNI Storage"); 367 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 374 ALOGV("setup: lpJniStorage: %p visualizer_ref %p visualizer_class %p, &mCallbackData %p", 375 lpJniStorage, 376 lpJniStorage->mCallbackData.visualizer_ref, 377 lpJniStorage->mCallbackData.visualizer_class, 378 &lpJniStorage->mCallbackData); 379 380 if (jId == NULL) { 381 ALOGE("setup: NULL java array for id pointer"); 382 lStatus = VISUALIZER_ERROR_BAD_VALUE; 383 goto setup_failure; 384 } 385 386 // create the native Visualizer object 387 lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()), 388 0, 389 android_media_visualizer_effect_callback, 390 lpJniStorage, 391 sessionId); 392 if (lpVisualizer == 0) { 393 ALOGE("Error creating Visualizer"); 394 goto setup_failure; 395 } 396 397 lStatus = translateError(lpVisualizer->initCheck()); 398 if (lStatus != VISUALIZER_SUCCESS && lStatus != VISUALIZER_ERROR_ALREADY_EXISTS) { 399 ALOGE("Visualizer initCheck failed %d", lStatus); 400 goto setup_failure; 401 } 402 403 nId = (jint *) env->GetPrimitiveArrayCritical(jId, NULL); 404 if (nId == NULL) { 405 ALOGE("setup: Error retrieving id pointer"); 406 lStatus = VISUALIZER_ERROR_BAD_VALUE; 407 goto setup_failure; 408 } 409 nId[0] = lpVisualizer->id(); 410 env->ReleasePrimitiveArrayCritical(jId, nId, 0); 411 nId = NULL; 412 413 setVisualizer(env, thiz, lpVisualizer); 414 415 env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage); 416 417 return VISUALIZER_SUCCESS; 418 419 // failures: 420 setup_failure: 421 422 if (nId != NULL) { 423 env->ReleasePrimitiveArrayCritical(jId, nId, 0); 424 } 425 426 if (lpJniStorage) { 427 env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_class); 428 env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_ref); 429 delete lpJniStorage; 430 } 431 env->SetLongField(thiz, fields.fidJniData, 0); 432 433 return (jint) lStatus; 434 } 435 436 // ---------------------------------------------------------------------------- 437 static void android_media_visualizer_native_release(JNIEnv *env, jobject thiz) { 438 sp<Visualizer> lpVisualizer = setVisualizer(env, thiz, 0); 439 if (lpVisualizer == 0) { 440 return; 441 } 442 443 // delete the JNI data 444 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 451 if (lpJniStorage) { 452 ALOGV("deleting pJniStorage: %p\n", lpJniStorage); 453 env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_class); 454 env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_ref); 455 delete lpJniStorage; 456 } 457 } 458 459 static 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); 462 } 463 464 // ---------------------------------------------------------------------------- 465 static jint 466 android_media_visualizer_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled) 467 { 468 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 469 if (lpVisualizer == 0) { 470 return VISUALIZER_ERROR_NO_INIT; 471 } 472 473 jint retVal = translateError(lpVisualizer->setEnabled(enabled)); 474 475 if (!enabled) { 476 VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage *)env->GetLongField( 477 thiz, fields.fidJniData); 478 479 if (NULL != lpJniStorage) 480 lpJniStorage->mCallbackData.cleanupBuffers(); 481 } 482 483 return retVal; 484 } 485 486 static jboolean 487 android_media_visualizer_native_getEnabled(JNIEnv *env, jobject thiz) 488 { 489 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 490 if (lpVisualizer == 0) { 491 return JNI_FALSE; 492 } 493 494 if (lpVisualizer->getEnabled()) { 495 return JNI_TRUE; 496 } else { 497 return JNI_FALSE; 498 } 499 } 500 501 static jintArray 502 android_media_visualizer_native_getCaptureSizeRange(JNIEnv *env, jobject /* thiz */) 503 { 504 jintArray jRange = env->NewIntArray(2); 505 jint *nRange = env->GetIntArrayElements(jRange, NULL); 506 nRange[0] = Visualizer::getMinCaptureSize(); 507 nRange[1] = Visualizer::getMaxCaptureSize(); 508 ALOGV("getCaptureSizeRange() min %d max %d", nRange[0], nRange[1]); 509 env->ReleaseIntArrayElements(jRange, nRange, 0); 510 return jRange; 511 } 512 513 static jint 514 android_media_visualizer_native_getMaxCaptureRate(JNIEnv* /* env */, jobject /* thiz */) 515 { 516 return (jint) Visualizer::getMaxCaptureRate(); 517 } 518 519 static jint 520 android_media_visualizer_native_setCaptureSize(JNIEnv *env, jobject thiz, jint size) 521 { 522 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 523 if (lpVisualizer == 0) { 524 return VISUALIZER_ERROR_NO_INIT; 525 } 526 527 return translateError(lpVisualizer->setCaptureSize(size)); 528 } 529 530 static jint 531 android_media_visualizer_native_getCaptureSize(JNIEnv *env, jobject thiz) 532 { 533 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 534 if (lpVisualizer == 0) { 535 return -1; 536 } 537 return (jint) lpVisualizer->getCaptureSize(); 538 } 539 540 static jint 541 android_media_visualizer_native_setScalingMode(JNIEnv *env, jobject thiz, jint mode) 542 { 543 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 544 if (lpVisualizer == 0) { 545 return VISUALIZER_ERROR_NO_INIT; 546 } 547 548 return translateError(lpVisualizer->setScalingMode(mode)); 549 } 550 551 static jint 552 android_media_visualizer_native_getScalingMode(JNIEnv *env, jobject thiz) 553 { 554 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 555 if (lpVisualizer == 0) { 556 return -1; 557 } 558 return (jint)lpVisualizer->getScalingMode(); 559 } 560 561 static jint 562 android_media_visualizer_native_setMeasurementMode(JNIEnv *env, jobject thiz, jint mode) 563 { 564 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 565 if (lpVisualizer == 0) { 566 return VISUALIZER_ERROR_NO_INIT; 567 } 568 return translateError(lpVisualizer->setMeasurementMode(mode)); 569 } 570 571 static jint 572 android_media_visualizer_native_getMeasurementMode(JNIEnv *env, jobject thiz) 573 { 574 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 575 if (lpVisualizer == 0) { 576 return MEASUREMENT_MODE_NONE; 577 } 578 return lpVisualizer->getMeasurementMode(); 579 } 580 581 static jint 582 android_media_visualizer_native_getSamplingRate(JNIEnv *env, jobject thiz) 583 { 584 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 585 if (lpVisualizer == 0) { 586 return -1; 587 } 588 return (jint) lpVisualizer->getSamplingRate(); 589 } 590 591 static jint 592 android_media_visualizer_native_getWaveForm(JNIEnv *env, jobject thiz, jbyteArray jWaveform) 593 { 594 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 595 if (lpVisualizer == 0) { 596 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); 606 return status; 607 } 608 609 static jint 610 android_media_visualizer_native_getFft(JNIEnv *env, jobject thiz, jbyteArray jFft) 611 { 612 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 613 if (lpVisualizer == 0) { 614 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 628 static jint 629 android_media_visualizer_native_getPeakRms(JNIEnv *env, jobject thiz, jobject jPeakRmsObj) 630 { 631 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 632 if (lpVisualizer == 0) { 633 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 647 static jint 648 android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean jWaveform, jboolean jFft) 649 { 650 sp<Visualizer> lpVisualizer = getVisualizer(env, thiz); 651 if (lpVisualizer == 0) { 652 return VISUALIZER_ERROR_NO_INIT; 653 } 654 VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage *)env->GetLongField(thiz, 655 fields.fidJniData); 656 if (lpJniStorage == NULL) { 657 return VISUALIZER_ERROR_NO_INIT; 658 } 659 660 ALOGV("setPeriodicCapture: rate %d, jWaveform %d jFft %d", 661 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 680 static JNINativeMethod gMethods[] = { 681 {"native_init", "()V", (void *)android_media_visualizer_native_init}, 682 {"native_setup", "(Ljava/lang/Object;I[ILjava/lang/String;)I", 683 (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}, 692 {"native_setScalingMode", "(I)I", (void *)android_media_visualizer_native_setScalingMode}, 693 {"native_getScalingMode", "()I", (void *)android_media_visualizer_native_getScalingMode}, 694 {"native_setMeasurementMode","(I)I", (void *)android_media_visualizer_native_setMeasurementMode}, 695 {"native_getMeasurementMode","()I", (void *)android_media_visualizer_native_getMeasurementMode}, 696 {"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}, 699 {"native_getPeakRms", "(Landroid/media/audiofx/Visualizer$MeasurementPeakRms;)I", 700 (void *)android_media_visualizer_native_getPeakRms}, 701 {"native_setPeriodicCapture","(IZZ)I",(void *)android_media_setPeriodicCapture}, 702 }; 703 704 // ---------------------------------------------------------------------------- 705 706 int register_android_media_visualizer(JNIEnv *env) 707 { 708 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 709 } 710 711