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 using 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 42 #define NATIVE_EVENT_SERVER_DIED 2 43 44 // ---------------------------------------------------------------------------- 45 static const char* const kClassPathName = "android/media/audiofx/Visualizer"; 46 static const char* const kClassPeakRmsPathName = 47 "android/media/audiofx/Visualizer$MeasurementPeakRms"; 48 49 struct 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 55 jfieldID fidPeak; // to access Visualizer.MeasurementPeakRms.mPeak 56 jfieldID fidRms; // to access Visualizer.MeasurementPeakRms.mRms 57 }; 58 static fields_t fields; 59 60 struct visualizer_callback_cookie { 61 jclass visualizer_class; // Visualizer class 62 jobject visualizer_ref; // Visualizer object instance 63 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 } 100 }; 101 102 // ---------------------------------------------------------------------------- 103 class visualizerJniStorage { 104 public: 105 visualizer_callback_cookie mCallbackData; 106 107 visualizerJniStorage() { 108 } 109 110 ~visualizerJniStorage() { 111 } 112 }; 113 114 115 static 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 // ---------------------------------------------------------------------------- 138 static 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 158 static 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(); 171 172 if (!user || !env) { 173 ALOGW("captureCallback error user %p, env %p", user, env); 174 return; 175 } 176 177 ALOGV("captureCallback: callbackInfo %p, visualizer_ref %p visualizer_class %p", 178 callbackInfo, 179 callbackInfo->visualizer_ref, 180 callbackInfo->visualizer_class); 181 182 AutoMutex lock(&callbackInfo->callback_data_lock); 183 184 if (waveformSize != 0 && waveform != NULL) { 185 jbyteArray jArray; 186 187 ensureArraySize(env, &callbackInfo->waveform_data, waveformSize); 188 jArray = callbackInfo->waveform_data; 189 190 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) { 206 jbyteArray jArray; 207 208 ensureArraySize(env, &callbackInfo->fft_data, fftSize); 209 jArray = callbackInfo->fft_data; 210 211 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); 223 } 224 } 225 226 if (env->ExceptionCheck()) { 227 env->ExceptionDescribe(); 228 env->ExceptionClear(); 229 } 230 } 231 232 static Visualizer *getVisualizer(JNIEnv* env, jobject thiz) 233 { 234 Visualizer *v = (Visualizer *)env->GetLongField( 235 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. 247 static void 248 android_media_visualizer_native_init(JNIEnv *env) 249 { 250 251 ALOGV("android_media_visualizer_native_init"); 252 253 fields.clazzEffect = NULL; 254 255 // Get the Visualizer class 256 jclass clazz = env->FindClass(kClassPathName); 257 if (clazz == NULL) { 258 ALOGE("Can't find %s", kClassPathName); 259 return; 260 } 261 262 fields.clazzEffect = (jclass)env->NewGlobalRef(clazz); 263 264 // 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 272 // 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) { 277 ALOGE("Can't find Visualizer.%s", "postEventFromNative"); 278 return; 279 } 280 281 // Get the variables fields 282 // nativeTrackInJavaObj 283 fields.fidNativeVisualizer = env->GetFieldID( 284 fields.clazzEffect, 285 "mNativeVisualizer", "J"); 286 if (fields.fidNativeVisualizer == NULL) { 287 ALOGE("Can't find Visualizer.%s", "mNativeVisualizer"); 288 return; 289 } 290 // fidJniData; 291 fields.fidJniData = env->GetFieldID( 292 fields.clazzEffect, 293 "mJniData", "J"); 294 if (fields.fidJniData == NULL) { 295 ALOGE("Can't find Visualizer.%s", "mJniData"); 296 return; 297 } 298 // 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 } 314 315 env->DeleteGlobalRef(clazzMeasurementPeakRms); 316 } 317 318 static 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, NULL); 333 } 334 } 335 336 static jint 337 android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, 338 jint sessionId, jintArray jId) 339 { 340 ALOGV("android_media_visualizer_native_setup"); 341 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) { 348 ALOGE("setup: Error creating JNI Storage"); 349 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 356 ALOGV("setup: lpJniStorage: %p visualizer_ref %p visualizer_class %p, &mCallbackData %p", 357 lpJniStorage, 358 lpJniStorage->mCallbackData.visualizer_ref, 359 lpJniStorage->mCallbackData.visualizer_class, 360 &lpJniStorage->mCallbackData); 361 362 if (jId == NULL) { 363 ALOGE("setup: NULL java array for id pointer"); 364 lStatus = VISUALIZER_ERROR_BAD_VALUE; 365 goto setup_failure; 366 } 367 368 // create the native Visualizer object 369 lpVisualizer = new Visualizer(0, 370 android_media_visualizer_effect_callback, 371 lpJniStorage, 372 sessionId); 373 if (lpVisualizer == NULL) { 374 ALOGE("Error creating Visualizer"); 375 goto setup_failure; 376 } 377 378 lStatus = translateError(lpVisualizer->initCheck()); 379 if (lStatus != VISUALIZER_SUCCESS && lStatus != VISUALIZER_ERROR_ALREADY_EXISTS) { 380 ALOGE("Visualizer initCheck failed %d", lStatus); 381 goto setup_failure; 382 } 383 384 nId = (jint *) env->GetPrimitiveArrayCritical(jId, NULL); 385 if (nId == NULL) { 386 ALOGE("setup: Error retrieving id pointer"); 387 lStatus = VISUALIZER_ERROR_BAD_VALUE; 388 goto setup_failure; 389 } 390 nId[0] = lpVisualizer->id(); 391 env->ReleasePrimitiveArrayCritical(jId, nId, 0); 392 nId = NULL; 393 394 env->SetLongField(thiz, fields.fidNativeVisualizer, (jlong)lpVisualizer); 395 396 env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage); 397 398 return VISUALIZER_SUCCESS; 399 400 // failures: 401 setup_failure: 402 403 if (nId != NULL) { 404 env->ReleasePrimitiveArrayCritical(jId, nId, 0); 405 } 406 407 if (lpVisualizer) { 408 delete lpVisualizer; 409 } 410 env->SetLongField(thiz, fields.fidNativeVisualizer, 0); 411 412 if (lpJniStorage) { 413 delete lpJniStorage; 414 } 415 env->SetLongField(thiz, fields.fidJniData, 0); 416 417 return (jint) lStatus; 418 } 419 420 // ---------------------------------------------------------------------------- 421 static void android_media_visualizer_native_finalize(JNIEnv *env, jobject thiz) { 422 ALOGV("android_media_visualizer_native_finalize jobject: %p\n", thiz); 423 424 // delete the Visualizer object 425 Visualizer* lpVisualizer = (Visualizer *)env->GetLongField( 426 thiz, fields.fidNativeVisualizer); 427 if (lpVisualizer) { 428 ALOGV("deleting Visualizer: %p\n", lpVisualizer); 429 delete lpVisualizer; 430 } 431 432 // delete the JNI data 433 visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField( 434 thiz, fields.fidJniData); 435 if (lpJniStorage) { 436 ALOGV("deleting pJniStorage: %p\n", lpJniStorage); 437 delete lpJniStorage; 438 } 439 } 440 441 // ---------------------------------------------------------------------------- 442 static 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. 448 env->SetLongField(thiz, fields.fidNativeVisualizer, 0); 449 env->SetLongField(thiz, fields.fidJniData, 0); 450 } 451 452 static jint 453 android_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 460 jint retVal = translateError(lpVisualizer->setEnabled(enabled)); 461 462 if (!enabled) { 463 visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField( 464 thiz, fields.fidJniData); 465 466 if (NULL != lpJniStorage) 467 lpJniStorage->mCallbackData.cleanupBuffers(); 468 } 469 470 return retVal; 471 } 472 473 static jboolean 474 android_media_visualizer_native_getEnabled(JNIEnv *env, jobject thiz) 475 { 476 Visualizer* lpVisualizer = getVisualizer(env, thiz); 477 if (lpVisualizer == NULL) { 478 return JNI_FALSE; 479 } 480 481 if (lpVisualizer->getEnabled()) { 482 return JNI_TRUE; 483 } else { 484 return JNI_FALSE; 485 } 486 } 487 488 static jintArray 489 android_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(); 495 ALOGV("getCaptureSizeRange() min %d max %d", nRange[0], nRange[1]); 496 env->ReleaseIntArrayElements(jRange, nRange, 0); 497 return jRange; 498 } 499 500 static jint 501 android_media_visualizer_native_getMaxCaptureRate(JNIEnv *env, jobject thiz) 502 { 503 return (jint) Visualizer::getMaxCaptureRate(); 504 } 505 506 static jint 507 android_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 517 static jint 518 android_media_visualizer_native_getCaptureSize(JNIEnv *env, jobject thiz) 519 { 520 Visualizer* lpVisualizer = getVisualizer(env, thiz); 521 if (lpVisualizer == NULL) { 522 return -1; 523 } 524 return (jint) lpVisualizer->getCaptureSize(); 525 } 526 527 static jint 528 android_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 538 static jint 539 android_media_visualizer_native_getScalingMode(JNIEnv *env, jobject thiz) 540 { 541 Visualizer* lpVisualizer = getVisualizer(env, thiz); 542 if (lpVisualizer == NULL) { 543 return -1; 544 } 545 return (jint)lpVisualizer->getScalingMode(); 546 } 547 548 static jint 549 android_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 558 static jint 559 android_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 568 static jint 569 android_media_visualizer_native_getSamplingRate(JNIEnv *env, jobject thiz) 570 { 571 Visualizer* lpVisualizer = getVisualizer(env, thiz); 572 if (lpVisualizer == NULL) { 573 return -1; 574 } 575 return (jint) lpVisualizer->getSamplingRate(); 576 } 577 578 static jint 579 android_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); 593 return status; 594 } 595 596 static jint 597 android_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 615 static jint 616 android_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 634 static jint 635 android_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 } 641 visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(thiz, 642 fields.fidJniData); 643 if (lpJniStorage == NULL) { 644 return VISUALIZER_ERROR_NO_INIT; 645 } 646 647 ALOGV("setPeriodicCapture: rate %d, jWaveform %d jFft %d", 648 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 667 static 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}, 679 {"native_setScalingMode", "(I)I", (void *)android_media_visualizer_native_setScalingMode}, 680 {"native_getScalingMode", "()I", (void *)android_media_visualizer_native_getScalingMode}, 681 {"native_setMeasurementMode","(I)I", (void *)android_media_visualizer_native_setMeasurementMode}, 682 {"native_getMeasurementMode","()I", (void *)android_media_visualizer_native_getMeasurementMode}, 683 {"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}, 686 {"native_getPeakRms", "(Landroid/media/audiofx/Visualizer$MeasurementPeakRms;)I", 687 (void *)android_media_visualizer_native_getPeakRms}, 688 {"native_setPeriodicCapture","(IZZ)I",(void *)android_media_setPeriodicCapture}, 689 }; 690 691 // ---------------------------------------------------------------------------- 692 693 int register_android_media_visualizer(JNIEnv *env) 694 { 695 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 696 } 697 698