/*
 * 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.media.audiofx.AudioEffect;
import android.util.Log;

import java.util.StringTokenizer;


/**
 * An Equalizer is used to alter the frequency response of a particular music source or of the main
 * output mix.
 * <p>An application creates an Equalizer object to instantiate and control an Equalizer engine
 * in the audio framework. The application can either simply use predefined presets or have a more
 * precise control of the gain in each frequency band controlled by the equalizer.
 * <p>The methods, parameter types and units exposed by the Equalizer implementation are directly
 * mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/)
 * for the SLEqualizerItf interface. Please refer to this specification for more details.
 * <p>To attach the Equalizer to a particular AudioTrack or MediaPlayer, specify the audio session
 * ID of this AudioTrack or MediaPlayer when constructing the Equalizer.
 * <p>NOTE: attaching an Equalizer to the global audio output mix by use of session 0 is deprecated.
 * <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
 * <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling audio
 * effects.
 */

public class Equalizer extends AudioEffect {

    private final static String TAG = "Equalizer";

    // These constants must be synchronized with those in
    // frameworks/base/include/media/EffectEqualizerApi.h
    /**
     * Number of bands. Parameter ID for OnParameterChangeListener
     */
    public static final int PARAM_NUM_BANDS = 0;
    /**
     * Band level range. Parameter ID for OnParameterChangeListener
     */
    public static final int PARAM_LEVEL_RANGE = 1;
    /**
     * Band level. Parameter ID for OnParameterChangeListener
     */
    public static final int PARAM_BAND_LEVEL = 2;
    /**
     * Band center frequency. Parameter ID for OnParameterChangeListener
     */
    public static final int PARAM_CENTER_FREQ = 3;
    /**
     * Band frequency range. Parameter ID for
     * {@link android.media.audiofx.Equalizer.OnParameterChangeListener}
     */
    public static final int PARAM_BAND_FREQ_RANGE = 4;
    /**
     * Band for a given frequency. Parameter ID for OnParameterChangeListener
     *
     */
    public static final int PARAM_GET_BAND = 5;
    /**
     * Current preset. Parameter ID for OnParameterChangeListener
     */
    public static final int PARAM_CURRENT_PRESET = 6;
    /**
     * Request number of presets. Parameter ID for OnParameterChangeListener
     */
    public static final int PARAM_GET_NUM_OF_PRESETS = 7;
    /**
     * Request preset name. Parameter ID for OnParameterChangeListener
     */
    public static final int PARAM_GET_PRESET_NAME = 8;
    // used by setProperties()/getProperties
    private static final int PARAM_PROPERTIES = 9;
    /**
     * Maximum size for preset name
     */
    public static final int PARAM_STRING_SIZE_MAX = 32;

    /**
     * Number of bands implemented by Equalizer engine
     */
    private short mNumBands = 0;

    /**
     * Number of presets implemented by Equalizer engine
     */
    private int mNumPresets;
    /**
     * Names of presets implemented by Equalizer engine
     */
    private String[] mPresetNames;

    /**
     * Registered listener for parameter changes.
     */
    private OnParameterChangeListener mParamListener = null;

    /**
     * Listener used internally to to receive raw parameter change event from AudioEffect super class
     */
    private BaseParameterListener mBaseParamListener = null;

    /**
     * Lock for access to mParamListener
     */
    private final Object mParamListenerLock = new Object();

    /**
     * Class constructor.
     * @param priority the priority level requested by the application for controlling the Equalizer
     * engine. As the same engine can be shared by several applications, this parameter indicates
     * how much the requesting application needs control of effect parameters. The normal priority
     * is 0, above normal is a positive number, below normal a negative number.
     * @param audioSession  system wide unique audio session identifier. The Equalizer will be
     * attached to the MediaPlayer or AudioTrack in the same audio session.
     *
     * @throws java.lang.IllegalStateException
     * @throws java.lang.IllegalArgumentException
     * @throws java.lang.UnsupportedOperationException
     * @throws java.lang.RuntimeException
     */
    public Equalizer(int priority, int audioSession)
    throws IllegalStateException, IllegalArgumentException,
           UnsupportedOperationException, RuntimeException {
        super(EFFECT_TYPE_EQUALIZER, EFFECT_TYPE_NULL, priority, audioSession);

        if (audioSession == 0) {
            Log.w(TAG, "WARNING: attaching an Equalizer to global output mix is deprecated!");
        }

        getNumberOfBands();

        mNumPresets = (int)getNumberOfPresets();

        if (mNumPresets != 0) {
            mPresetNames = new String[mNumPresets];
            byte[] value = new byte[PARAM_STRING_SIZE_MAX];
            int[] param = new int[2];
            param[0] = PARAM_GET_PRESET_NAME;
            for (int i = 0; i < mNumPresets; i++) {
                param[1] = i;
                checkStatus(getParameter(param, value));
                int length = 0;
                while (value[length] != 0) length++;
                try {
                    mPresetNames[i] = new String(value, 0, length, "ISO-8859-1");
                } catch (java.io.UnsupportedEncodingException e) {
                    Log.e(TAG, "preset name decode error");
                }
            }
        }
    }

    /**
     * Gets the number of frequency bands supported by the Equalizer engine.
     * @return the number of bands
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public short getNumberOfBands()
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        if (mNumBands != 0) {
            return mNumBands;
        }
        int[] param = new int[1];
        param[0] = PARAM_NUM_BANDS;
        short[] result = new short[1];
        checkStatus(getParameter(param, result));
        mNumBands = result[0];
        return mNumBands;
    }

    /**
     * Gets the level range for use by {@link #setBandLevel(short,short)}. The level is expressed in
     * milliBel.
     * @return the band level range in an array of short integers. The first element is the lower
     * limit of the range, the second element the upper limit.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public short[] getBandLevelRange()
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        short[] result = new short[2];
        checkStatus(getParameter(PARAM_LEVEL_RANGE, result));
        return result;
    }

    /**
     * Sets the given equalizer band to the given gain value.
     * @param band frequency band that will have the new gain. The numbering of the bands starts
     * from 0 and ends at (number of bands - 1).
     * @param level new gain in millibels that will be set to the given band. getBandLevelRange()
     * will define the maximum and minimum values.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     * @see #getNumberOfBands()
     */
    public void setBandLevel(short band, short level)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        int[] param = new int[2];
        short[] value = new short[1];

        param[0] = PARAM_BAND_LEVEL;
        param[1] = (int)band;
        value[0] = level;
        checkStatus(setParameter(param, value));
    }

    /**
     * Gets the gain set for the given equalizer band.
     * @param band frequency band whose gain is requested. The numbering of the bands starts
     * from 0 and ends at (number of bands - 1).
     * @return the gain in millibels of the given band.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public short getBandLevel(short band)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        int[] param = new int[2];
        short[] result = new short[1];

        param[0] = PARAM_BAND_LEVEL;
        param[1] = (int)band;
        checkStatus(getParameter(param, result));

        return result[0];
    }


    /**
     * Gets the center frequency of the given band.
     * @param band frequency band whose center frequency is requested. The numbering of the bands
     * starts from 0 and ends at (number of bands - 1).
     * @return the center frequency in milliHertz
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public int getCenterFreq(short band)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        int[] param = new int[2];
        int[] result = new int[1];

        param[0] = PARAM_CENTER_FREQ;
        param[1] = (int)band;
        checkStatus(getParameter(param, result));

        return result[0];
    }

    /**
     * Gets the frequency range of the given frequency band.
     * @param band frequency band whose frequency range is requested. The numbering of the bands
     * starts from 0 and ends at (number of bands - 1).
     * @return the frequency range in millHertz in an array of integers. The first element is the
     * lower limit of the range, the second element the upper limit.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public int[] getBandFreqRange(short band)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        int[] param = new int[2];
        int[] result = new int[2];
        param[0] = PARAM_BAND_FREQ_RANGE;
        param[1] = (int)band;
        checkStatus(getParameter(param, result));

        return result;
    }

    /**
     * Gets the band that has the most effect on the given frequency.
     * @param frequency frequency in milliHertz which is to be equalized via the returned band.
     * @return the frequency band that has most effect on the given frequency.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public short getBand(int frequency)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        int[] param = new int[2];
        short[] result = new short[1];

        param[0] = PARAM_GET_BAND;
        param[1] = frequency;
        checkStatus(getParameter(param, result));

        return result[0];
    }

    /**
     * Gets current preset.
     * @return the preset that is set at the moment.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public short getCurrentPreset()
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        short[] result = new short[1];
        checkStatus(getParameter(PARAM_CURRENT_PRESET, result));
        return result[0];
    }

    /**
     * Sets the equalizer according to the given preset.
     * @param preset new preset that will be taken into use. The valid range is [0,
     * number of presets-1].
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     * @see #getNumberOfPresets()
     */
    public void usePreset(short preset)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        checkStatus(setParameter(PARAM_CURRENT_PRESET, preset));
    }

    /**
     * Gets the total number of presets the equalizer supports. The presets will have indices
     * [0, number of presets-1].
     * @return the number of presets the equalizer supports.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public short getNumberOfPresets()
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        short[] result = new short[1];
        checkStatus(getParameter(PARAM_GET_NUM_OF_PRESETS, result));
        return result[0];
    }

    /**
     * Gets the preset name based on the index.
     * @param preset index of the preset. The valid range is [0, number of presets-1].
     * @return a string containing the name of the given preset.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public String getPresetName(short preset)
    {
        if (preset >= 0 && preset < mNumPresets) {
            return mPresetNames[preset];
        } else {
            return "";
        }
    }

    /**
     * The OnParameterChangeListener interface defines a method called by the Equalizer when a
     * parameter value has changed.
     */
    public interface OnParameterChangeListener  {
        /**
         * Method called when a parameter value has changed. The method is called only if the
         * parameter was changed by another application having the control of the same
         * Equalizer engine.
         * @param effect the Equalizer on which the interface is registered.
         * @param status status of the set parameter operation.
         * @param param1 ID of the modified parameter. See {@link #PARAM_BAND_LEVEL} ...
         * @param param2 additional parameter qualifier (e.g the band for band level parameter).
         * @param value the new parameter value.
         */
        void onParameterChange(Equalizer effect, int status, int param1, int param2, int value);
    }

    /**
     * Listener used internally to receive unformatted parameter change events from AudioEffect
     * super class.
     */
    private class BaseParameterListener implements AudioEffect.OnParameterChangeListener {
        private BaseParameterListener() {

        }
        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) {
            OnParameterChangeListener l = null;

            synchronized (mParamListenerLock) {
                if (mParamListener != null) {
                    l = mParamListener;
                }
            }
            if (l != null) {
                int p1 = -1;
                int p2 = -1;
                int v = -1;

                if (param.length >= 4) {
                    p1 = byteArrayToInt(param, 0);
                    if (param.length >= 8) {
                        p2 = byteArrayToInt(param, 4);
                    }
                }
                if (value.length == 2) {
                    v = (int)byteArrayToShort(value, 0);;
                } else if (value.length == 4) {
                    v = byteArrayToInt(value, 0);
                }

                if (p1 != -1 && v != -1) {
                    l.onParameterChange(Equalizer.this, status, p1, p2, v);
                }
            }
        }
    }

    /**
     * Registers an OnParameterChangeListener interface.
     * @param listener OnParameterChangeListener interface registered
     */
    public void setParameterListener(OnParameterChangeListener listener) {
        synchronized (mParamListenerLock) {
            if (mParamListener == null) {
                mParamListener = listener;
                mBaseParamListener = new BaseParameterListener();
                super.setParameterListener(mBaseParamListener);
            }
        }
    }

    /**
     * The Settings class regroups all equalizer parameters. It is used in
     * conjuntion with getProperties() and setProperties() methods to backup and restore
     * all parameters in a single call.
     */
    public static class Settings {
        public short curPreset;
        public short numBands = 0;
        public short[] bandLevels = null;

        public Settings() {
        }

        /**
         * Settings class constructor from a key=value; pairs formatted string. The string is
         * typically returned by Settings.toString() method.
         * @throws IllegalArgumentException if the string is not correctly formatted.
         */
        public Settings(String settings) {
            StringTokenizer st = new StringTokenizer(settings, "=;");
            int tokens = st.countTokens();
            if (st.countTokens() < 5) {
                throw new IllegalArgumentException("settings: " + settings);
            }
            String key = st.nextToken();
            if (!key.equals("Equalizer")) {
                throw new IllegalArgumentException(
                        "invalid settings for Equalizer: " + key);
            }
            try {
                key = st.nextToken();
                if (!key.equals("curPreset")) {
                    throw new IllegalArgumentException("invalid key name: " + key);
                }
                curPreset = Short.parseShort(st.nextToken());
                key = st.nextToken();
                if (!key.equals("numBands")) {
                    throw new IllegalArgumentException("invalid key name: " + key);
                }
                numBands = Short.parseShort(st.nextToken());
                if (st.countTokens() != numBands*2) {
                    throw new IllegalArgumentException("settings: " + settings);
                }
                bandLevels = new short[numBands];
                for (int i = 0; i < numBands; i++) {
                    key = st.nextToken();
                    if (!key.equals("band"+(i+1)+"Level")) {
                        throw new IllegalArgumentException("invalid key name: " + key);
                    }
                    bandLevels[i] = Short.parseShort(st.nextToken());
                }
             } catch (NumberFormatException nfe) {
                throw new IllegalArgumentException("invalid value for key: " + key);
            }
        }

        @Override
        public String toString() {

            String str = new String (
                    "Equalizer"+
                    ";curPreset="+Short.toString(curPreset)+
                    ";numBands="+Short.toString(numBands)
                    );
            for (int i = 0; i < numBands; i++) {
                str = str.concat(";band"+(i+1)+"Level="+Short.toString(bandLevels[i]));
            }
            return str;
        }
    };


    /**
     * Gets the equalizer properties. This method is useful when a snapshot of current
     * equalizer settings must be saved by the application.
     * @return an Equalizer.Settings object containing all current parameters values
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public Equalizer.Settings getProperties()
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        byte[] param = new byte[4 + mNumBands * 2];
        checkStatus(getParameter(PARAM_PROPERTIES, param));
        Settings settings = new Settings();
        settings.curPreset = byteArrayToShort(param, 0);
        settings.numBands = byteArrayToShort(param, 2);
        settings.bandLevels = new short[mNumBands];
        for (int i = 0; i < mNumBands; i++) {
            settings.bandLevels[i] = byteArrayToShort(param, 4 + 2*i);
        }
        return settings;
    }

    /**
     * Sets the equalizer properties. This method is useful when equalizer settings have to
     * be applied from a previous backup.
     * @param settings an Equalizer.Settings object containing the properties to apply
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public void setProperties(Equalizer.Settings settings)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        if (settings.numBands != settings.bandLevels.length ||
            settings.numBands != mNumBands) {
            throw new IllegalArgumentException("settings invalid band count: " +settings.numBands);
        }

        byte[] param = concatArrays(shortToByteArray(settings.curPreset),
                                    shortToByteArray(mNumBands));
        for (int i = 0; i < mNumBands; i++) {
            param = concatArrays(param,
                                 shortToByteArray(settings.bandLevels[i]));
        }
        checkStatus(setParameter(PARAM_PROPERTIES, param));
    }
}
