android_media_Visualizer.cpp revision 3540a0197f56c4bcd7d7419f4502bfca34257de2
1df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent/*
2df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * Copyright (C) 2010 The Android Open Source Project
3df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *
4df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * you may not use this file except in compliance with the License.
6df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * You may obtain a copy of the License at
7df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *
8df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent *
10df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * Unless required by applicable law or agreed to in writing, software
11df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * See the License for the specific language governing permissions and
14df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent * limitations under the License.
15df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent */
16df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
17df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#include <stdio.h>
18df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
19df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent//#define LOG_NDEBUG 0
20df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define LOG_TAG "visualizers-JNI"
21df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
22df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#include <utils/Log.h>
23df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#include <nativehelper/jni.h>
24df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#include <nativehelper/JNIHelp.h>
25df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#include <android_runtime/AndroidRuntime.h>
26449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman#include <utils/threads.h>
27df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#include "media/Visualizer.h"
28df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
29df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentusing namespace android;
30df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
31df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define VISUALIZER_SUCCESS                      0
32df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define VISUALIZER_ERROR                       -1
33df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define VISUALIZER_ERROR_ALREADY_EXISTS        -2
34df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define VISUALIZER_ERROR_NO_INIT               -3
35df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define VISUALIZER_ERROR_BAD_VALUE             -4
36df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define VISUALIZER_ERROR_INVALID_OPERATION     -5
37df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define VISUALIZER_ERROR_NO_MEMORY             -6
38df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define VISUALIZER_ERROR_DEAD_OBJECT           -7
39df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
40df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define NATIVE_EVENT_PCM_CAPTURE                0
41df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent#define NATIVE_EVENT_FFT_CAPTURE                1
423540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman#define NATIVE_EVENT_SERVER_DIED                2
43df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
44df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// ----------------------------------------------------------------------------
451a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurentstatic const char* const kClassPathName = "android/media/audiofx/Visualizer";
46df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
47df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstruct fields_t {
48df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // these fields provide access from C++ to the...
49df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jclass    clazzEffect;          // Visualizer class
50df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jmethodID midPostNativeEvent;   // event post callback method
51df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jfieldID  fidNativeVisualizer; // stores in Java the native Visualizer object
52df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jfieldID  fidJniData;           // stores in Java additional resources used by the native Visualizer
53df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent};
54df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic fields_t fields;
55df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
56df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstruct visualizer_callback_cookie {
57df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jclass      visualizer_class;  // Visualizer class
58df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jobject     visualizer_ref;    // Visualizer object instance
59449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
60449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    // Lazily allocated arrays used to hold callback data provided to java
61449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    // applications.  These arrays are allocated during the first callback and
62449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    // reallocated when the size of the callback data changes.  Allocating on
63449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    // demand and saving the arrays means that applications cannot safely hold a
64449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    // reference to the provided data (they need to make a copy if they want to
65449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    // hold onto outside of the callback scope), but it avoids GC thrash caused
66449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    // by constantly allocating and releasing arrays to hold callback data.
67449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    Mutex       callback_data_lock;
68449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    jbyteArray  waveform_data;
69449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    jbyteArray  fft_data;
70449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
71449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    visualizer_callback_cookie() {
72449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        waveform_data = NULL;
73449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        fft_data = NULL;
74449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    }
75449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
76449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    ~visualizer_callback_cookie() {
77449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        cleanupBuffers();
78449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    }
79449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
80449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    void cleanupBuffers() {
81449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        AutoMutex lock(&callback_data_lock);
82449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        if (waveform_data || fft_data) {
83449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman            JNIEnv *env = AndroidRuntime::getJNIEnv();
84449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
85449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman            if (waveform_data) {
86449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman                env->DeleteGlobalRef(waveform_data);
87449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman                waveform_data = NULL;
88449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman            }
89449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
90449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman            if (fft_data) {
91449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman                env->DeleteGlobalRef(fft_data);
92449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman                fft_data = NULL;
93449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman            }
94449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        }
95449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    }
96df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent };
97df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
98df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// ----------------------------------------------------------------------------
99df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentclass visualizerJniStorage {
100df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    public:
101df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        visualizer_callback_cookie mCallbackData;
102df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
103df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    visualizerJniStorage() {
104df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
105df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
106df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    ~visualizerJniStorage() {
107df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
108df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent};
109df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
110df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
111df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint translateError(int code) {
112df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    switch(code) {
113df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    case NO_ERROR:
114df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_SUCCESS;
115df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    case ALREADY_EXISTS:
116df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_ALREADY_EXISTS;
117df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    case NO_INIT:
118df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_INIT;
119df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    case BAD_VALUE:
120df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_BAD_VALUE;
121df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    case INVALID_OPERATION:
122df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_INVALID_OPERATION;
123df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    case NO_MEMORY:
124df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_MEMORY;
125df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    case DEAD_OBJECT:
126df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_DEAD_OBJECT;
127df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    default:
128df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR;
129df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
130df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
131df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
132df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
133df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// ----------------------------------------------------------------------------
134449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossmanstatic void ensureArraySize(JNIEnv *env, jbyteArray *array, uint32_t size) {
135449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    if (NULL != *array) {
136449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        uint32_t len = env->GetArrayLength(*array);
137449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        if (len == size)
138449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman            return;
139449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
140449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        env->DeleteGlobalRef(*array);
141449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        *array = NULL;
142449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    }
143449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
144449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    jbyteArray localRef = env->NewByteArray(size);
145449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    if (NULL != localRef) {
146449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        // Promote to global ref.
147449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        *array = (jbyteArray)env->NewGlobalRef(localRef);
148449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
149449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        // Release our (now pointless) local ref.
150449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        env->DeleteLocalRef(localRef);
151449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    }
152449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman}
153449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
154df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic void captureCallback(void* user,
155df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        uint32_t waveformSize,
156df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        uint8_t *waveform,
157df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        uint32_t fftSize,
158df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        uint8_t *fft,
159df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        uint32_t samplingrate) {
160df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
161df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    int arg1 = 0;
162df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    int arg2 = 0;
163df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    size_t size;
164df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
165df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    visualizer_callback_cookie *callbackInfo = (visualizer_callback_cookie *)user;
166df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    JNIEnv *env = AndroidRuntime::getJNIEnv();
167449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    AutoMutex lock(&callbackInfo->callback_data_lock);
168df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
16971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("captureCallback: callbackInfo %p, visualizer_ref %p visualizer_class %p",
170df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            callbackInfo,
171df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            callbackInfo->visualizer_ref,
172df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            callbackInfo->visualizer_class);
173df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
174df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (!user || !env) {
1758564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("captureCallback error user %p, env %p", user, env);
176df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return;
177df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
178df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
179df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (waveformSize != 0 && waveform != NULL) {
180449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        jbyteArray jArray;
181449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
182449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        ensureArraySize(env, &callbackInfo->waveform_data, waveformSize);
183449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        jArray = callbackInfo->waveform_data;
184449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
185df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        if (jArray != NULL) {
186df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            jbyte *nArray = env->GetByteArrayElements(jArray, NULL);
187df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            memcpy(nArray, waveform, waveformSize);
188df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            env->ReleaseByteArrayElements(jArray, nArray, 0);
189df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            env->CallStaticVoidMethod(
190df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                callbackInfo->visualizer_class,
191df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                fields.midPostNativeEvent,
192df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                callbackInfo->visualizer_ref,
193df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                NATIVE_EVENT_PCM_CAPTURE,
194df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                samplingrate,
195df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                0,
196df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                jArray);
197df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
198df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
199df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
200df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (fftSize != 0 && fft != NULL) {
201449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        jbyteArray jArray;
202449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
203449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        ensureArraySize(env, &callbackInfo->fft_data, fftSize);
204449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        jArray = callbackInfo->fft_data;
205449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
206df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        if (jArray != NULL) {
207df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            jbyte *nArray = env->GetByteArrayElements(jArray, NULL);
208df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            memcpy(nArray, fft, fftSize);
209df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            env->ReleaseByteArrayElements(jArray, nArray, 0);
210df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            env->CallStaticVoidMethod(
211df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                callbackInfo->visualizer_class,
212df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                fields.midPostNativeEvent,
213df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                callbackInfo->visualizer_ref,
214df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                NATIVE_EVENT_FFT_CAPTURE,
215df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                samplingrate,
216df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                0,
217df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                jArray);
218df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        }
219df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
220df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
221df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (env->ExceptionCheck()) {
222df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        env->ExceptionDescribe();
223df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        env->ExceptionClear();
224df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
225df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
226df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
227df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic Visualizer *getVisualizer(JNIEnv* env, jobject thiz)
228df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
229df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer *v = (Visualizer *)env->GetIntField(
230df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        thiz, fields.fidNativeVisualizer);
231df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (v == NULL) {
232df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        jniThrowException(env, "java/lang/IllegalStateException",
233df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            "Unable to retrieve Visualizer pointer");
234df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
235df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return v;
236df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
237df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
238df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// ----------------------------------------------------------------------------
239df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// This function gets some field IDs, which in turn causes class initialization.
240df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// It is called from a static block in Visualizer, which won't run until the
241df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// first time an instance of this class is used.
242df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic void
243df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_init(JNIEnv *env)
244df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
245df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
24671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("android_media_visualizer_native_init");
247df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
248df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    fields.clazzEffect = NULL;
249df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
250df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Get the Visualizer class
251df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jclass clazz = env->FindClass(kClassPathName);
252df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (clazz == NULL) {
2533762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find %s", kClassPathName);
254df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return;
255df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
256df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
257df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    fields.clazzEffect = (jclass)env->NewGlobalRef(clazz);
258df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
259df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Get the postEvent method
260df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    fields.midPostNativeEvent = env->GetStaticMethodID(
261df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            fields.clazzEffect,
262df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V");
263df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (fields.midPostNativeEvent == NULL) {
2643762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find Visualizer.%s", "postEventFromNative");
265df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return;
266df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
267df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
268df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // Get the variables fields
269df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //      nativeTrackInJavaObj
270df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    fields.fidNativeVisualizer = env->GetFieldID(
271df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            fields.clazzEffect,
272df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            "mNativeVisualizer", "I");
273df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (fields.fidNativeVisualizer == NULL) {
2743762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find Visualizer.%s", "mNativeVisualizer");
275df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return;
276df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
277df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    //      fidJniData;
278df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    fields.fidJniData = env->GetFieldID(
279df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            fields.clazzEffect,
280df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            "mJniData", "I");
281df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (fields.fidJniData == NULL) {
2823762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find Visualizer.%s", "mJniData");
283df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return;
284df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
285df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
286df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
287df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
2883540a0197f56c4bcd7d7419f4502bfca34257de2John Grossmanstatic void android_media_visualizer_effect_callback(int32_t event,
2893540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                                                     void *user,
2903540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                                                     void *info) {
2913540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    if ((event == AudioEffect::EVENT_ERROR) &&
2923540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        (*((status_t*)info) == DEAD_OBJECT)) {
2933540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        visualizerJniStorage* lpJniStorage = (visualizerJniStorage*)user;
2943540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        visualizer_callback_cookie* callbackInfo = &lpJniStorage->mCallbackData;
2953540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        JNIEnv *env = AndroidRuntime::getJNIEnv();
2963540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman
2973540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman        env->CallStaticVoidMethod(
2983540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            callbackInfo->visualizer_class,
2993540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            fields.midPostNativeEvent,
3003540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            callbackInfo->visualizer_ref,
3013540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            NATIVE_EVENT_SERVER_DIED,
3023540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman            0, 0, 0);
3033540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman    }
3043540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman}
305df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
306df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
307df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
308df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        jint sessionId, jintArray jId)
309df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
31071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("android_media_visualizer_native_setup");
311df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    visualizerJniStorage* lpJniStorage = NULL;
312df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    int lStatus = VISUALIZER_ERROR_NO_MEMORY;
313df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = NULL;
314df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jint* nId = NULL;
315df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
316df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    lpJniStorage = new visualizerJniStorage();
317df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpJniStorage == NULL) {
3183762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("setup: Error creating JNI Storage");
319df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        goto setup_failure;
320df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
321df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
322df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    lpJniStorage->mCallbackData.visualizer_class = (jclass)env->NewGlobalRef(fields.clazzEffect);
323df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // we use a weak reference so the Visualizer object can be garbage collected.
324df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    lpJniStorage->mCallbackData.visualizer_ref = env->NewGlobalRef(weak_this);
325df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
32671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("setup: lpJniStorage: %p visualizer_ref %p visualizer_class %p, &mCallbackData %p",
327df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            lpJniStorage,
328df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            lpJniStorage->mCallbackData.visualizer_ref,
329df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            lpJniStorage->mCallbackData.visualizer_class,
330df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            &lpJniStorage->mCallbackData);
331df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
3322fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    if (jId == NULL) {
3333762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("setup: NULL java array for id pointer");
334df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        lStatus = VISUALIZER_ERROR_BAD_VALUE;
335df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        goto setup_failure;
336df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
337df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
338df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // create the native Visualizer object
339df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    lpVisualizer = new Visualizer(0,
3403540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                                  android_media_visualizer_effect_callback,
3413540a0197f56c4bcd7d7419f4502bfca34257de2John Grossman                                  lpJniStorage,
342df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                                  sessionId);
343df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
3443762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Error creating Visualizer");
345df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        goto setup_failure;
346df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
347df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
348df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    lStatus = translateError(lpVisualizer->initCheck());
349df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lStatus != VISUALIZER_SUCCESS && lStatus != VISUALIZER_ERROR_ALREADY_EXISTS) {
3503762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Visualizer initCheck failed %d", lStatus);
351df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        goto setup_failure;
352df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
353df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
3542fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    nId = (jint *) env->GetPrimitiveArrayCritical(jId, NULL);
3552fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    if (nId == NULL) {
3563762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("setup: Error retrieving id pointer");
3572fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent        lStatus = VISUALIZER_ERROR_BAD_VALUE;
3582fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent        goto setup_failure;
3592fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    }
360df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    nId[0] = lpVisualizer->id();
361df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->ReleasePrimitiveArrayCritical(jId, nId, 0);
362df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    nId = NULL;
363df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
364df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->SetIntField(thiz, fields.fidNativeVisualizer, (int)lpVisualizer);
365df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
366df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->SetIntField(thiz, fields.fidJniData, (int)lpJniStorage);
367df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
368df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return VISUALIZER_SUCCESS;
369df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
370df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // failures:
371df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentsetup_failure:
372df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
373df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (nId != NULL) {
374df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        env->ReleasePrimitiveArrayCritical(jId, nId, 0);
375df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
376df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
377df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer) {
378df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        delete lpVisualizer;
379df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
380df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->SetIntField(thiz, fields.fidNativeVisualizer, 0);
381df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
382df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpJniStorage) {
383df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        delete lpJniStorage;
384df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
385df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->SetIntField(thiz, fields.fidJniData, 0);
386df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
387df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return lStatus;
388df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
389df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
390df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// ----------------------------------------------------------------------------
391df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic void android_media_visualizer_native_finalize(JNIEnv *env,  jobject thiz) {
39271f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("android_media_visualizer_native_finalize jobject: %x\n", (int)thiz);
393df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
394df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // delete the Visualizer object
395df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = (Visualizer *)env->GetIntField(
396df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        thiz, fields.fidNativeVisualizer);
397df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer) {
39871f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("deleting Visualizer: %x\n", (int)lpVisualizer);
399df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        delete lpVisualizer;
400df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
401df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
402df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // delete the JNI data
403df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetIntField(
404df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        thiz, fields.fidJniData);
405df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpJniStorage) {
40671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        ALOGV("deleting pJniStorage: %x\n", (int)lpJniStorage);
407df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        delete lpJniStorage;
408df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
409df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
410df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
411df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// ----------------------------------------------------------------------------
412df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic void android_media_visualizer_native_release(JNIEnv *env,  jobject thiz) {
413df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
414df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // do everything a call to finalize would
415df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    android_media_visualizer_native_finalize(env, thiz);
416df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // + reset the native resources in the Java object so any attempt to access
417df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    // them after a call to release fails.
418df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->SetIntField(thiz, fields.fidNativeVisualizer, 0);
419df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->SetIntField(thiz, fields.fidJniData, 0);
420df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
421df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
422df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
423df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
424df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
425df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = getVisualizer(env, thiz);
426df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
427df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_INIT;
428df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
429df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
430449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    jint retVal = translateError(lpVisualizer->setEnabled(enabled));
431449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
432449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    if (!enabled) {
433449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetIntField(
434449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman            thiz, fields.fidJniData);
435449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
436449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman        if (NULL != lpJniStorage)
437449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman            lpJniStorage->mCallbackData.cleanupBuffers();
438449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    }
439449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman
440449725f9aa67136a38c7554ba76ac4e27e5e3bd3John Grossman    return retVal;
441df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
442df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
443df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jboolean
444df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_getEnabled(JNIEnv *env, jobject thiz)
445df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
446df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = getVisualizer(env, thiz);
447df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
448df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return false;
449df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
450df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
451df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return (jboolean)lpVisualizer->getEnabled();
452df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
453df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
454df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jintArray
455df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_getCaptureSizeRange(JNIEnv *env, jobject thiz)
456df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
457df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jintArray jRange = env->NewIntArray(2);
458df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jint *nRange = env->GetIntArrayElements(jRange, NULL);
459df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    nRange[0] = Visualizer::getMinCaptureSize();
460df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    nRange[1] = Visualizer::getMaxCaptureSize();
46171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("getCaptureSizeRange() min %d max %d", nRange[0], nRange[1]);
462df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->ReleaseIntArrayElements(jRange, nRange, 0);
463df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return jRange;
464df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
465df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
466df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
467df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_getMaxCaptureRate(JNIEnv *env, jobject thiz)
468df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
469df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return Visualizer::getMaxCaptureRate();
470df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
471df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
472df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
473df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_setCaptureSize(JNIEnv *env, jobject thiz, jint size)
474df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
475df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = getVisualizer(env, thiz);
476df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
477df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_INIT;
478df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
479df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
480df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return translateError(lpVisualizer->setCaptureSize(size));
481df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
482df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
483df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
484df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_getCaptureSize(JNIEnv *env, jobject thiz)
485df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
486df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = getVisualizer(env, thiz);
487df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
488df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return -1;
489df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
490df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return lpVisualizer->getCaptureSize();
491df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
492df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
493df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
494df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_getSamplingRate(JNIEnv *env, jobject thiz)
495df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
496df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = getVisualizer(env, thiz);
497df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
498df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return -1;
499df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
500df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return lpVisualizer->getSamplingRate();
501df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
502df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
503df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
504df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_getWaveForm(JNIEnv *env, jobject thiz, jbyteArray jWaveform)
505df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
506df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = getVisualizer(env, thiz);
507df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
508df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_INIT;
509df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
510df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
511df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jbyte* nWaveform = (jbyte *) env->GetPrimitiveArrayCritical(jWaveform, NULL);
512df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (nWaveform == NULL) {
513df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_MEMORY;
514df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
515df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jint status = translateError(lpVisualizer->getWaveForm((uint8_t *)nWaveform));
516df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
517df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->ReleasePrimitiveArrayCritical(jWaveform, nWaveform, 0);
518df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return status;
519df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
520df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
521df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
522df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_visualizer_native_getFft(JNIEnv *env, jobject thiz, jbyteArray jFft)
523df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
524df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = getVisualizer(env, thiz);
525df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
526df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_INIT;
527df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
528df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
529df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jbyte* nFft = (jbyte *) env->GetPrimitiveArrayCritical(jFft, NULL);
530df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (nFft == NULL) {
531df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_MEMORY;
532df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
533df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    jint status = translateError(lpVisualizer->getFft((uint8_t *)nFft));
534df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
535df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    env->ReleasePrimitiveArrayCritical(jFft, nFft, 0);
536df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
537df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return status;
538df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
539df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
540df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic jint
541df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentandroid_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean jWaveform, jboolean jFft)
542df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
543df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer* lpVisualizer = getVisualizer(env, thiz);
544df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpVisualizer == NULL) {
545df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_INIT;
546df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
547df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetIntField(thiz,
548df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            fields.fidJniData);
549df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (lpJniStorage == NULL) {
550df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent        return VISUALIZER_ERROR_NO_INIT;
551df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    }
552df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
55371f2cf116aab893e224056c38ab146bd1538dd3eSteve Block    ALOGV("setPeriodicCapture: rate %d, jWaveform %d jFft %d",
554df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            rate,
555df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            jWaveform,
556df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent            jFft);
557df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
558df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    uint32_t flags = Visualizer::CAPTURE_CALL_JAVA;
559df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (jWaveform) flags |= Visualizer::CAPTURE_WAVEFORM;
560df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (jFft) flags |= Visualizer::CAPTURE_FFT;
561df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    Visualizer::capture_cbk_t cbk = captureCallback;
562df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    if (!jWaveform && !jFft) cbk = NULL;
563df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
564df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return translateError(lpVisualizer->setCaptureCallBack(cbk,
565df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                                                &lpJniStorage->mCallbackData,
566df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                                                flags,
567df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                                                rate));
568df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
569df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
570df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// ----------------------------------------------------------------------------
571df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
572df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// Dalvik VM type signatures
573df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentstatic JNINativeMethod gMethods[] = {
574df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_init",            "()V",     (void *)android_media_visualizer_native_init},
575df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_setup",           "(Ljava/lang/Object;I[I)I",
576df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent                                          (void *)android_media_visualizer_native_setup},
577df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_finalize",          "()V",   (void *)android_media_visualizer_native_finalize},
578df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_release",           "()V",   (void *)android_media_visualizer_native_release},
579df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_setEnabled",        "(Z)I",  (void *)android_media_visualizer_native_setEnabled},
580df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_getEnabled",        "()Z",   (void *)android_media_visualizer_native_getEnabled},
581df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"getCaptureSizeRange",      "()[I",  (void *)android_media_visualizer_native_getCaptureSizeRange},
582df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"getMaxCaptureRate",        "()I",   (void *)android_media_visualizer_native_getMaxCaptureRate},
583df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_setCaptureSize",    "(I)I",  (void *)android_media_visualizer_native_setCaptureSize},
584df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_getCaptureSize",    "()I",   (void *)android_media_visualizer_native_getCaptureSize},
585df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_getSamplingRate",   "()I",   (void *)android_media_visualizer_native_getSamplingRate},
586df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_getWaveForm",       "([B)I", (void *)android_media_visualizer_native_getWaveForm},
587df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_getFft",            "([B)I", (void *)android_media_visualizer_native_getFft},
588df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    {"native_setPeriodicCapture","(IZZ)I",(void *)android_media_setPeriodicCapture},
589df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent};
590df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
591df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent// ----------------------------------------------------------------------------
592df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
593df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurentint register_android_media_visualizer(JNIEnv *env)
594df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent{
595df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
596df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent}
597df9b81ced437b11f8a3fcf4ba3ea6af703d121e2Eric Laurent
598