/*
 *    Copyright (C) 2014 Haruki Hasegawa
 *
 *    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 com.h6ah4i.android.media.opensl;

import android.content.Context;
import android.media.AudioManager;
import android.util.Log;

import com.h6ah4i.android.media.IReleasable;
import com.h6ah4i.android.media.utils.AudioSystemUtils;
import com.h6ah4i.android.media.utils.AudioSystemUtils.AudioSystemProperties;

public class OpenSLMediaPlayerContext implements IReleasable {
    private static final String TAG = "OpenSLMediaPlayerCtx";

    // options
    public static final int OPTION_USE_BASSBOOST = (1 << 0);
    public static final int OPTION_USE_VIRTUALIZER = (1 << 1);
    public static final int OPTION_USE_EQUALIZER = (1 << 2);
    public static final int OPTION_USE_ENVIRONMENAL_REVERB = (1 << 8);
    public static final int OPTION_USE_PRESET_REVERB = (1 << 9);
    public static final int OPTION_USE_VISUALIZER = (1 << 16);
    public static final int OPTION_USE_HQ_EQUALIZER = (1 << 17);
    public static final int OPTION_USE_PREAMP = (1 << 18);
    public static final int OPTION_USE_HQ_VISUALIZER = (1 << 19);

    // resampler quality specifiler
    public static final int RESAMPLER_QUALITY_LOW = 0;
    public static final int RESAMPLER_QUALITY_MIDDLE = 1;
    public static final int RESAMPLER_QUALITY_HIGH = 2;

    // HQEqualizer implementation type specifier
    public static final int HQ_EAUALIZER_IMPL_BASIC_PEAKING_FILTER = 0;
    public static final int HQ_EAUALIZER_IMPL_FLAT_GAIN_RESPONSE = 1;

    // Sink back-end implementation type specifier
    public static final int SINK_BACKEND_TYPE_OPENSL = 0;
    public static final int SINK_BACKEND_TYPE_AUDIO_TRACK = 1;

    private long mNativeHandle;
    private static final boolean HAS_NATIVE;
    private boolean mHasNative;
    private AudioSystemUtils.AudioSystemProperties mProperties;

    static {
        // load native library
        HAS_NATIVE = OpenSLMediaPlayerNativeLibraryLoader.loadLibraries();
    }

    public static class Parameters {
        public int options = 0;
        public int streamType = AudioManager.STREAM_MUSIC;
        public int shortFadeDuration = 25; // [milli seconds]
        public int longFadeDuration = 1500; // [milli seconds]
        public int resamplerQuality = RESAMPLER_QUALITY_MIDDLE;
        public int hqEqualizerImplType = HQ_EAUALIZER_IMPL_BASIC_PEAKING_FILTER;
        public int sinkBackEndType = SINK_BACKEND_TYPE_OPENSL;
        public boolean useLowLatencyIfAvailable = false;
        public boolean useFloatingPointIfAvailable = true;
    }

    public OpenSLMediaPlayerContext(Context context, Parameters params) {
        final AudioSystemProperties props = AudioSystemUtils.getProperties(context);

        if (params == null) {
            params = new Parameters();
        }

        boolean hasNative = false;
        if (HAS_NATIVE) {
            try {
                final int[] iparams = new int[13];

                iparams[0] = props.outputSampleRate * 1000; // [Hz] -> [milli hertz]
                iparams[1] = props.outputFramesPerBuffer;
                iparams[2] = props.supportLowLatency ? 1 : 0;
                iparams[3] = props.supportFloatingPoint ? 1 : 0;
                iparams[4] = params.options;
                iparams[5] = params.streamType;
                iparams[6] = params.shortFadeDuration;
                iparams[7] = params.longFadeDuration;
                iparams[8] = params.resamplerQuality;
                iparams[9] = params.hqEqualizerImplType;
                iparams[10] = params.sinkBackEndType;
                iparams[11] = params.useLowLatencyIfAvailable ? 1 : 0;
                iparams[12] = params.useFloatingPointIfAvailable ? 1 : 0;

                mNativeHandle = createNativeImplHandle(iparams);
                if (mNativeHandle != 0) {
                    hasNative = true;
                }
            } catch (Throwable e) {
            }
        }
        mHasNative = hasNative;
        mProperties = props;
    }

    @Override
    protected void finalize() throws Throwable {
        release();
        super.finalize();
    }

    @Override
    public void release() {
        try {
            if (mHasNative && mNativeHandle != 0) {
                deleteNativeImplHandle(mNativeHandle);
                mNativeHandle = 0;
            }
        } catch (Exception e) {
            Log.e(TAG, "release()", e);
        }
    }

    //
    // Internal methods
    //

    /** @hide */
    /* package */long getNativeHandle() {
        return mNativeHandle;
    }

    /** @hide */
    /* package */
    int getAudioSessionId() {
        return getAudioSessionIdImplNative(mNativeHandle);
    }

    //
    // Native methods
    //
    private static native long createNativeImplHandle(int[] params);

    private static native void deleteNativeImplHandle(long handle);

    private static native int getAudioSessionIdImplNative(long handle);
}

@@ -3097,27 +3097,28 @@
 Available = 
-tru
+fals
 e;%0A    %7D%0A%0A  

Disable the useLowLatencyIfAvailable option by default