/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.audiofx;

import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import java.lang.ref.WeakReference;

/**
 * The Visualizer class enables application to retrieve part of the currently playing audio for
 * visualization purpose. It is not an audio recording interface and only returns partial and low
 * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use
 * of the visualizer requires the permission android.permission.RECORD_AUDIO.
 * <p>The audio session ID passed to the constructor indicates which audio content should be
 * visualized:<br>
 * <ul>
 *   <li>If the session is 0, the audio output mix is visualized</li>
 *   <li>If the session is not 0, the audio from a particular {@link android.media.MediaPlayer} or
 *   {@link android.media.AudioTrack}
 *   using this audio session is visualized </li>
 * </ul>
 * <p>Two types of representation of audio content can be captured: <br>
 * <ul>
 *   <li>Waveform data: consecutive 8-bit (unsigned) mono samples by using the
 *   {@link #getWaveForm(byte[])} method</li>
 *   <li>Frequency data: 8-bit magnitude FFT by using the {@link #getFft(byte[])} method</li>
 * </ul>
 * <p>The length of the capture can be retrieved or specified by calling respectively
 * {@link #getCaptureSize()} and {@link #setCaptureSize(int)} methods. The capture size must be a
 * power of 2 in the range returned by {@link #getCaptureSizeRange()}.
 * <p>In addition to the polling capture mode described above with {@link #getWaveForm(byte[])} and
 *  {@link #getFft(byte[])} methods, a callback mode is also available by installing a listener by
 *  use of the {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method.
 *  The rate at which the listener capture method is called as well as the type of data returned is
 *  specified.
 * <p>Before capturing data, the Visualizer must be enabled by calling the
 * {@link #setEnabled(boolean)} method.
 * When data capture is not needed any more, the Visualizer should be disabled.
 * <p>It is good practice to call the {@link #release()} method when the Visualizer is not used
 * anymore to free up native resources associated to the Visualizer instance.
 * <p>Creating a Visualizer on the output mix (audio session 0) requires permission
 * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
 * <p>The Visualizer class can also be used to perform measurements on the audio being played back.
 * The measurements to perform are defined by setting a mask of the requested measurement modes with
 * {@link #setMeasurementMode(int)}. Supported values are {@link #MEASUREMENT_MODE_NONE} to cancel
 * any measurement, and {@link #MEASUREMENT_MODE_PEAK_RMS} for peak and RMS monitoring.
 * Measurements can be retrieved through {@link #getMeasurementPeakRms(MeasurementPeakRms)}.
 */

public class Visualizer {

    static {
        System.loadLibrary("audioeffect_jni");
        native_init();
    }

    private final static String TAG = "Visualizer-JAVA";

    /**
     * State of a Visualizer object that was not successfully initialized upon creation
     */
    public static final int STATE_UNINITIALIZED = 0;
    /**
     * State of a Visualizer object that is ready to be used.
     */
    public static final int STATE_INITIALIZED   = 1;
    /**
     * State of a Visualizer object that is active.
     */
    public static final int STATE_ENABLED   = 2;

    // to keep in sync with system/media/audio_effects/include/audio_effects/effect_visualizer.h
    /**
     * Defines a capture mode where amplification is applied based on the content of the captured
     * data. This is the default Visualizer mode, and is suitable for music visualization.
     */
    public static final int SCALING_MODE_NORMALIZED = 0;
    /**
     * Defines a capture mode where the playback volume will affect (scale) the range of the
     * captured data. A low playback volume will lead to low sample and fft values, and vice-versa.
     */
    public static final int SCALING_MODE_AS_PLAYED = 1;

    /**
     * Defines a measurement mode in which no measurements are performed.
     */
    public static final int MEASUREMENT_MODE_NONE = 0;

    /**
     * Defines a measurement mode which computes the peak and RMS value in mB, where 0mB is the
     * maximum sample value, and -9600mB is the minimum value.
     * Values for peak and RMS can be retrieved with
     * {@link #getMeasurementPeakRms(MeasurementPeakRms)}.
     */
    public static final int MEASUREMENT_MODE_PEAK_RMS = 1 << 0;

    // to keep in sync with frameworks/base/media/jni/audioeffect/android_media_Visualizer.cpp
    private static final int NATIVE_EVENT_PCM_CAPTURE = 0;
    private static final int NATIVE_EVENT_FFT_CAPTURE = 1;
    private static final int NATIVE_EVENT_SERVER_DIED = 2;

    // Error codes:
    /**
     * Successful operation.
     */
    public  static final int SUCCESS              = 0;
    /**
     * Unspecified error.
     */
    public  static final int ERROR                = -1;
    /**
     * Internal operation status. Not returned by any method.
     */
    public  static final int ALREADY_EXISTS       = -2;
    /**
     * Operation failed due to bad object initialization.
     */
    public  static final int ERROR_NO_INIT              = -3;
    /**
     * Operation failed due to bad parameter value.
     */
    public  static final int ERROR_BAD_VALUE            = -4;
    /**
     * Operation failed because it was requested in wrong state.
     */
    public  static final int ERROR_INVALID_OPERATION    = -5;
    /**
     * Operation failed due to lack of memory.
     */
    public  static final int ERROR_NO_MEMORY            = -6;
    /**
     * Operation failed due to dead remote object.
     */
    public  static final int ERROR_DEAD_OBJECT          = -7;

    //--------------------------------------------------------------------------
    // Member variables
    //--------------------
    /**
     * Indicates the state of the Visualizer instance
     */
    private int mState = STATE_UNINITIALIZED;
    /**
     * Lock to synchronize access to mState
     */
    private final Object mStateLock = new Object();
    /**
     * System wide unique Identifier of the visualizer engine used by this Visualizer instance
     */
    @UnsupportedAppUsage
    private int mId;

    /**
     * Lock to protect listeners updates against event notifications
     */
    private final Object mListenerLock = new Object();
    /**
     * Handler for events coming from the native code
     */
    private NativeEventHandler mNativeEventHandler = null;
    /**
     *  PCM and FFT capture listener registered by client
     */
    private OnDataCaptureListener mCaptureListener = null;
    /**
     *  Server Died listener registered by client
     */
    private OnServerDiedListener mServerDiedListener = null;

    // accessed by native methods
    private long mNativeVisualizer;
    private long mJniData;

    //--------------------------------------------------------------------------
    // Constructor, Finalize
    //--------------------
    /**
     * Class constructor.
     * @param audioSession system wide unique audio session identifier. If audioSession
     *  is not 0, the visualizer will be attached to the MediaPlayer or AudioTrack in the
     *  same audio session. Otherwise, the Visualizer will apply to the output mix.
     *
     * @throws java.lang.UnsupportedOperationException
     * @throws java.lang.RuntimeException
     */

    public Visualizer(int audioSession)
    throws UnsupportedOperationException, RuntimeException {
        int[] id = new int[1];

        synchronized (mStateLock) {
            mState = STATE_UNINITIALIZED;
            // native initialization
            int result = native_setup(new WeakReference<Visualizer>(this), audioSession, id,
                    ActivityThread.currentOpPackageName());
            if (result != SUCCESS && result != ALREADY_EXISTS) {
                Log.e(TAG, "Error code "+result+" when initializing Visualizer.");
                switch (result) {
                case ERROR_INVALID_OPERATION:
                    throw (new UnsupportedOperationException("Effect library not loaded"));
                default:
                    throw (new RuntimeException("Cannot initialize Visualizer engine, error: "
                            +result));
                }
            }
            mId = id[0];
            if (native_getEnabled()) {
                mState = STATE_ENABLED;
            } else {
                mState = STATE_INITIALIZED;
            }
        }
    }

    /**
     * Releases the native Visualizer resources. It is a good practice to release the
     * visualization engine when not in use.
     */
    public void release() {
        synchronized (mStateLock) {
            native_release();
            mState = STATE_UNINITIALIZED;
        }
    }

    @Override
    protected void finalize() {
        native_finalize();
    }

    /**
     * Enable or disable the visualization engine.
     * @param enabled requested enable state
     * @return {@link #SUCCESS} in case of success,
     * {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT} in case of failure.
     * @throws IllegalStateException
     */
    public int setEnabled(boolean enabled)
    throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("setEnabled() called in wrong state: "+mState));
            }
            int status = SUCCESS;
            if ((enabled && (mState == STATE_INITIALIZED)) ||
                    (!enabled && (mState == STATE_ENABLED))) {
                status = native_setEnabled(enabled);
                if (status == SUCCESS) {
                    mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
                }
            }
            return status;
        }
    }

    /**
     * Get current activation state of the visualizer.
     * @return true if the visualizer is active, false otherwise
     */
    public boolean getEnabled()
    {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getEnabled() called in wrong state: "+mState));
            }
            return native_getEnabled();
        }
    }

    /**
     * Returns the capture size range.
     * @return the mininum capture size is returned in first array element and the maximum in second
     * array element.
     */
    public static native int[] getCaptureSizeRange();

    /**
     * Returns the maximum capture rate for the callback capture method. This is the maximum value
     * for the rate parameter of the
     * {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method.
     * @return the maximum capture rate expressed in milliHertz
     */
    public static native int getMaxCaptureRate();

    /**
     * Sets the capture size, i.e. the number of bytes returned by {@link #getWaveForm(byte[])} and
     * {@link #getFft(byte[])} methods. The capture size must be a power of 2 in the range returned
     * by {@link #getCaptureSizeRange()}.
     * This method must not be called when the Visualizer is enabled.
     * @param size requested capture size
     * @return {@link #SUCCESS} in case of success,
     * {@link #ERROR_BAD_VALUE} in case of failure.
     * @throws IllegalStateException
     */
    public int setCaptureSize(int size)
    throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState != STATE_INITIALIZED) {
                throw(new IllegalStateException("setCaptureSize() called in wrong state: "+mState));
            }
            return native_setCaptureSize(size);
        }
    }

    /**
     * Returns current capture size.
     * @return the capture size in bytes.
     */
    public int getCaptureSize()
    throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getCaptureSize() called in wrong state: "+mState));
            }
            return native_getCaptureSize();
        }
    }

    /**
     * Set the type of scaling applied on the captured visualization data.
     * @param mode see {@link #SCALING_MODE_NORMALIZED}
     *     and {@link #SCALING_MODE_AS_PLAYED}
     * @return {@link #SUCCESS} in case of success,
     *     {@link #ERROR_BAD_VALUE} in case of failure.
     * @throws IllegalStateException
     */
    public int setScalingMode(int mode)
    throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("setScalingMode() called in wrong state: "
                        + mState));
            }
            return native_setScalingMode(mode);
        }
    }

    /**
     * Returns the current scaling mode on the captured visualization data.
     * @return the scaling mode, see {@link #SCALING_MODE_NORMALIZED}
     *     and {@link #SCALING_MODE_AS_PLAYED}.
     * @throws IllegalStateException
     */
    public int getScalingMode()
    throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getScalingMode() called in wrong state: "
                        + mState));
            }
            return native_getScalingMode();
        }
    }

    /**
     * Sets the combination of measurement modes to be performed by this audio effect.
     * @param mode a mask of the measurements to perform. The valid values are
     *     {@link #MEASUREMENT_MODE_NONE} (to cancel any measurement)
     *     or {@link #MEASUREMENT_MODE_PEAK_RMS}.
     * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE} in case of failure.
     * @throws IllegalStateException
     */
    public int setMeasurementMode(int mode)
            throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("setMeasurementMode() called in wrong state: "
                        + mState));
            }
            return native_setMeasurementMode(mode);
        }
    }

    /**
     * Returns the current measurement modes performed by this audio effect
     * @return the mask of the measurements,
     *     {@link #MEASUREMENT_MODE_NONE} (when no measurements are performed)
     *     or {@link #MEASUREMENT_MODE_PEAK_RMS}.
     * @throws IllegalStateException
     */
    public int getMeasurementMode()
            throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getMeasurementMode() called in wrong state: "
                        + mState));
            }
            return native_getMeasurementMode();
        }
    }

    /**
     * Returns the sampling rate of the captured audio.
     * @return the sampling rate in milliHertz.
     */
    public int getSamplingRate()
    throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState == STATE_UNINITIALIZED) {
                throw(new IllegalStateException("getSamplingRate() called in wrong state: "+mState));
            }
            return native_getSamplingRate();
        }
    }

    /**
     * Returns a waveform capture of currently playing audio content. The capture consists in
     * a number of consecutive 8-bit (unsigned) mono PCM samples equal to the capture size returned
     * by {@link #getCaptureSize()}.
     * <p>This method must be called when the Visualizer is enabled.
     * @param waveform array of bytes where the waveform should be returned
     * @return {@link #SUCCESS} in case of success,
     * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT}
     * in case of failure.
     * @throws IllegalStateException
     */
    public int getWaveForm(byte[] waveform)
    throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState != STATE_ENABLED) {
                throw(new IllegalStateException("getWaveForm() called in wrong state: "+mState));
            }
            return native_getWaveForm(waveform);
        }
    }
    /**
     * Returns a frequency capture of currently playing audio content.
     * <p>This method must be called when the Visualizer is enabled.
     * <p>The capture is an 8-bit magnitude FFT, the frequency range covered being 0 (DC) to half of
     * the sampling rate returned by {@link #getSamplingRate()}. The capture returns the real and
     * imaginary parts of a number of frequency points equal to half of the capture size plus one.
     * <p>Note: only the real part is returned for the first point (DC) and the last point
     * (sampling frequency / 2).
     * <p>The layout in the returned byte array is as follows:
     * <ul>
     *   <li> n is the capture size returned by getCaptureSize()</li>
     *   <li> Rfk, Ifk are respectively  the real and imaginary parts of the kth frequency
     *   component</li>
     *   <li> If Fs is the sampling frequency retuned by getSamplingRate() the kth frequency is:
     *   k * Fs / n </li>
     * </ul>
     * <table border="0" cellspacing="0" cellpadding="0">
     * <tr><td>Index </p></td>
     *     <td>0 </p></td>
     *     <td>1 </p></td>
     *     <td>2 </p></td>
     *     <td>3 </p></td>
     *     <td>4 </p></td>
     *     <td>5 </p></td>
     *     <td>... </p></td>
     *     <td>n - 2 </p></td>
     *     <td>n - 1 </p></td></tr>
     * <tr><td>Data </p></td>
     *     <td>Rf0 </p></td>
     *     <td>Rf(n/2) </p></td>
     *     <td>Rf1 </p></td>
     *     <td>If1 </p></td>
     *     <td>Rf2 </p></td>
     *     <td>If2 </p></td>
     *     <td>... </p></td>
     *     <td>Rf(n/2-1) </p></td>
     *     <td>If(n/2-1) </p></td></tr>
     * </table>
     * <p>In order to obtain magnitude and phase values the following code can
     * be used:
     *    <pre class="prettyprint">
     *       int n = fft.size();
     *       float[] magnitudes = new float[n / 2 + 1];
     *       float[] phases = new float[n / 2 + 1];
     *       magnitudes[0] = (float)Math.abs(fft[0]);      // DC
     *       magnitudes[n / 2] = (float)Math.abs(fft[1]);  // Nyquist
     *       phases[0] = phases[n / 2] = 0;
     *       for (int k = 1; k &lt; n / 2; k++) {
     *           int i = k * 2;
     *           magnitudes[k] = (float)Math.hypot(fft[i], fft[i + 1]);
     *           phases[k] = (float)Math.atan2(fft[i + 1], fft[i]);
     *       }</pre>
     * @param fft array of bytes where the FFT should be returned
     * @return {@link #SUCCESS} in case of success,
     * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT}
     * in case of failure.
     * @throws IllegalStateException
     */
    public int getFft(byte[] fft)
    throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState != STATE_ENABLED) {
                throw(new IllegalStateException("getFft() called in wrong state: "+mState));
            }
            return native_getFft(fft);
        }
    }

    /**
     * A class to store peak and RMS values.
     * Peak and RMS are expressed in mB, as described in the
     * {@link Visualizer#MEASUREMENT_MODE_PEAK_RMS} measurement mode.
     */
    public static final class MeasurementPeakRms {
        /**
         * The peak value in mB.
         */
        public int mPeak;
        /**
         * The RMS value in mB.
         */
        public int mRms;
    }

    /**
     * Retrieves the latest peak and RMS measurement.
     * Sets the peak and RMS fields of the supplied {@link Visualizer.MeasurementPeakRms} to the
     * latest measured values.
     * @param measurement a non-null {@link Visualizer.MeasurementPeakRms} instance to store
     *    the measurement values.
     * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE},
     *    {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT}
     *    in case of failure.
     */
    public int getMeasurementPeakRms(MeasurementPeakRms measurement) {
        if (measurement == null) {
            Log.e(TAG, "Cannot store measurements in a null object");
            return ERROR_BAD_VALUE;
        }
        synchronized (mStateLock) {
            if (mState != STATE_ENABLED) {
                throw (new IllegalStateException("getMeasurementPeakRms() called in wrong state: "
                        + mState));
            }
            return native_getPeakRms(measurement);
        }
    }

    //---------------------------------------------------------
    // Interface definitions
    //--------------------
    /**
     * The OnDataCaptureListener interface defines methods called by the Visualizer to periodically
     * update the audio visualization capture.
     * The client application can implement this interface and register the listener with the
     * {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method.
     */
    public interface OnDataCaptureListener  {
        /**
         * Method called when a new waveform capture is available.
         * <p>Data in the waveform buffer is valid only within the scope of the callback.
         * Applications which need access to the waveform data after returning from the callback
         * should make a copy of the data instead of holding a reference.
         * @param visualizer Visualizer object on which the listener is registered.
         * @param waveform array of bytes containing the waveform representation.
         * @param samplingRate sampling rate of the visualized audio.
         */
        void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate);

        /**
         * Method called when a new frequency capture is available.
         * <p>Data in the fft buffer is valid only within the scope of the callback.
         * Applications which need access to the fft data after returning from the callback
         * should make a copy of the data instead of holding a reference.
         * <p>For the explanation of the fft data array layout, and the example
         * code for processing it, please see the documentation for {@link #getFft(byte[])} method.
         *
         * @param visualizer Visualizer object on which the listener is registered.
         * @param fft array of bytes containing the frequency representation.
         * @param samplingRate sampling rate of the visualized audio.
         */
        void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate);
    }

    /**
     * Registers an OnDataCaptureListener interface and specifies the rate at which the capture
     * should be updated as well as the type of capture requested.
     * <p>Call this method with a null listener to stop receiving the capture updates.
     * @param listener OnDataCaptureListener registered
     * @param rate rate in milliHertz at which the capture should be updated
     * @param waveform true if a waveform capture is requested: the onWaveFormDataCapture()
     * method will be called on the OnDataCaptureListener interface.
     * @param fft true if a frequency capture is requested: the onFftDataCapture() method will be
     * called on the OnDataCaptureListener interface.
     * @return {@link #SUCCESS} in case of success,
     * {@link #ERROR_NO_INIT} or {@link #ERROR_BAD_VALUE} in case of failure.
     */
    public int setDataCaptureListener(OnDataCaptureListener listener,
            int rate, boolean waveform, boolean fft) {
        synchronized (mListenerLock) {
            mCaptureListener = listener;
        }
        if (listener == null) {
            // make sure capture callback is stopped in native code
            waveform = false;
            fft = false;
        }
        int status = native_setPeriodicCapture(rate, waveform, fft);
        if (status == SUCCESS) {
            if ((listener != null) && (mNativeEventHandler == null)) {
                Looper looper;
                if ((looper = Looper.myLooper()) != null) {
                    mNativeEventHandler = new NativeEventHandler(this, looper);
                } else if ((looper = Looper.getMainLooper()) != null) {
                    mNativeEventHandler = new NativeEventHandler(this, looper);
                } else {
                    mNativeEventHandler = null;
                    status = ERROR_NO_INIT;
                }
            }
        }
        return status;
    }

    /**
     * @hide
     *
     * The OnServerDiedListener interface defines a method called by the Visualizer to indicate that
     * the connection to the native media server has been broken and that the Visualizer object will
     * need to be released and re-created.
     * The client application can implement this interface and register the listener with the
     * {@link #setServerDiedListener(OnServerDiedListener)} method.
     */
    public interface OnServerDiedListener  {
        /**
         * @hide
         *
         * Method called when the native media server has died.
         * <p>If the native media server encounters a fatal error and needs to restart, the binder
         * connection from the {@link #Visualizer} to the media server will be broken.  Data capture
         * callbacks will stop happening, and client initiated calls to the {@link #Visualizer}
         * instance will fail with the error code {@link #DEAD_OBJECT}.  To restore functionality,
         * clients should {@link #release()} their old visualizer and create a new instance.
         */
        void onServerDied();
    }

    /**
     * @hide
     *
     * Registers an OnServerDiedListener interface.
     * <p>Call this method with a null listener to stop receiving server death notifications.
     * @return {@link #SUCCESS} in case of success,
     */
    public int setServerDiedListener(OnServerDiedListener listener) {
        synchronized (mListenerLock) {
            mServerDiedListener = listener;
        }
        return SUCCESS;
    }

    /**
     * Helper class to handle the forwarding of native events to the appropriate listeners
     */
    private class NativeEventHandler extends Handler
    {
        private Visualizer mVisualizer;

        public NativeEventHandler(Visualizer v, Looper looper) {
            super(looper);
            mVisualizer = v;
        }

        private void handleCaptureMessage(Message msg) {
            OnDataCaptureListener l = null;
            synchronized (mListenerLock) {
                l = mVisualizer.mCaptureListener;
            }

            if (l != null) {
                byte[] data = (byte[])msg.obj;
                int samplingRate = msg.arg1;

                switch(msg.what) {
                case NATIVE_EVENT_PCM_CAPTURE:
                    l.onWaveFormDataCapture(mVisualizer, data, samplingRate);
                    break;
                case NATIVE_EVENT_FFT_CAPTURE:
                    l.onFftDataCapture(mVisualizer, data, samplingRate);
                    break;
                default:
                    Log.e(TAG,"Unknown native event in handleCaptureMessge: "+msg.what);
                    break;
                }
            }
        }

        private void handleServerDiedMessage(Message msg) {
            OnServerDiedListener l = null;
            synchronized (mListenerLock) {
                l = mVisualizer.mServerDiedListener;
            }

            if (l != null)
                l.onServerDied();
        }

        @Override
        public void handleMessage(Message msg) {
            if (mVisualizer == null) {
                return;
            }

            switch(msg.what) {
            case NATIVE_EVENT_PCM_CAPTURE:
            case NATIVE_EVENT_FFT_CAPTURE:
                handleCaptureMessage(msg);
                break;
            case NATIVE_EVENT_SERVER_DIED:
                handleServerDiedMessage(msg);
                break;
            default:
                Log.e(TAG,"Unknown native event: "+msg.what);
                break;
            }
        }
    }

    //---------------------------------------------------------
    // Interface definitions
    //--------------------

    private static native final void native_init();

    private native final int native_setup(Object audioeffect_this,
                                          int audioSession,
                                          int[] id,
                                          String opPackageName);

    private native final void native_finalize();

    private native final void native_release();

    private native final int native_setEnabled(boolean enabled);

    private native final boolean native_getEnabled();

    private native final int native_setCaptureSize(int size);

    private native final int native_getCaptureSize();

    private native final int native_setScalingMode(int mode);

    private native final int native_getScalingMode();

    private native final int native_setMeasurementMode(int mode);

    private native final int native_getMeasurementMode();

    private native final int native_getSamplingRate();

    private native final int native_getWaveForm(byte[] waveform);

    private native final int native_getFft(byte[] fft);

    private native final int native_getPeakRms(MeasurementPeakRms measurement);

    private native final int native_setPeriodicCapture(int rate, boolean waveForm, boolean fft);

    //---------------------------------------------------------
    // Java methods called from the native side
    //--------------------
    @SuppressWarnings("unused")
    private static void postEventFromNative(Object effect_ref,
            int what, int arg1, int arg2, Object obj) {
        Visualizer visu = (Visualizer)((WeakReference)effect_ref).get();
        if (visu == null) {
            return;
        }

        if (visu.mNativeEventHandler != null) {
            Message m = visu.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
            visu.mNativeEventHandler.sendMessage(m);
        }

    }
}

