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

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.StringTokenizer;


/**
 * An audio virtualizer is a general name for an effect to spatialize audio channels. The exact
 * behavior of this effect is dependent on the number of audio input channels and the types and
 * number of audio output channels of the device. For example, in the case of a stereo input and
 * stereo headphone output, a stereo widening effect is used when this effect is turned on.
 * <p>An application creates a Virtualizer object to instantiate and control a virtualizer engine
 * in the audio framework.
 * <p>The methods, parameter types and units exposed by the Virtualizer implementation are directly
 * mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/)
 * for the SLVirtualizerItf interface. Please refer to this specification for more details.
 * <p>To attach the Virtualizer to a particular AudioTrack or MediaPlayer, specify the audio session
 * ID of this AudioTrack or MediaPlayer when constructing the Virtualizer.
 * <p>NOTE: attaching a Virtualizer 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 Virtualizer extends AudioEffect {

    private final static String TAG = "Virtualizer";
    private final static boolean DEBUG = false;

    // These constants must be synchronized with those in
    //        system/media/audio_effects/include/audio_effects/effect_virtualizer.h
    /**
     * Is strength parameter supported by virtualizer engine. Parameter ID for getParameter().
     */
    public static final int PARAM_STRENGTH_SUPPORTED = 0;
    /**
     * Virtualizer effect strength. Parameter ID for
     * {@link android.media.audiofx.Virtualizer.OnParameterChangeListener}
     */
    public static final int PARAM_STRENGTH = 1;
    /**
     * @hide
     * Parameter ID to query the virtual speaker angles for a channel mask / device configuration.
     */
    public static final int PARAM_VIRTUAL_SPEAKER_ANGLES = 2;
    /**
     * @hide
     * Parameter ID to force the virtualization mode to be that of a specific device
     */
    public static final int PARAM_FORCE_VIRTUALIZATION_MODE = 3;
    /**
     * @hide
     * Parameter ID to query the current virtualization mode.
     */
    public static final int PARAM_VIRTUALIZATION_MODE = 4;

    /**
     * Indicates if strength parameter is supported by the virtualizer engine
     */
    private boolean mStrengthSupported = false;

    /**
     * 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 Virtualizer
     * 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 Virtualizer 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 Virtualizer(int priority, int audioSession)
    throws IllegalStateException, IllegalArgumentException,
           UnsupportedOperationException, RuntimeException {
        super(EFFECT_TYPE_VIRTUALIZER, EFFECT_TYPE_NULL, priority, audioSession);

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

        int[] value = new int[1];
        checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value));
        mStrengthSupported = (value[0] != 0);
    }

    /**
     * Indicates whether setting strength is supported. If this method returns false, only one
     * strength is supported and the setStrength() method always rounds to that value.
     * @return true is strength parameter is supported, false otherwise
     */
    public boolean getStrengthSupported() {
       return mStrengthSupported;
    }

    /**
     * Sets the strength of the virtualizer effect. If the implementation does not support per mille
     * accuracy for setting the strength, it is allowed to round the given strength to the nearest
     * supported value. You can use the {@link #getRoundedStrength()} method to query the
     * (possibly rounded) value that was actually set.
     * @param strength strength of the effect. The valid range for strength strength is [0, 1000],
     * where 0 per mille designates the mildest effect and 1000 per mille designates the strongest.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public void setStrength(short strength)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        checkStatus(setParameter(PARAM_STRENGTH, strength));
    }

    /**
     * Gets the current strength of the effect.
     * @return the strength of the effect. The valid range for strength is [0, 1000], where 0 per
     * mille designates the mildest effect and 1000 per mille the strongest
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public short getRoundedStrength()
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        short[] value = new short[1];
        checkStatus(getParameter(PARAM_STRENGTH, value));
        return value[0];
    }

    /**
     * Checks if a configuration is supported, and query the virtual speaker angles.
     * @param inputChannelMask
     * @param deviceType
     * @param angles if non-null: array in which the angles will be written. If null, no angles
     *    are returned
     * @return true if the combination of channel mask and output device type is supported, false
     *    otherwise
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    private boolean getAnglesInt(int inputChannelMask, int deviceType, int[] angles)
            throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        // parameter check
        if (inputChannelMask == AudioFormat.CHANNEL_INVALID) {
            throw (new IllegalArgumentException(
                    "Virtualizer: illegal CHANNEL_INVALID channel mask"));
        }
        int channelMask = inputChannelMask == AudioFormat.CHANNEL_OUT_DEFAULT ?
                AudioFormat.CHANNEL_OUT_STEREO : inputChannelMask;
        int nbChannels = AudioFormat.channelCountFromOutChannelMask(channelMask);
        if ((angles != null) && (angles.length < (nbChannels * 3))) {
            Log.e(TAG, "Size of array for angles cannot accomodate number of channels in mask ("
                    + nbChannels + ")");
            throw (new IllegalArgumentException(
                    "Virtualizer: array for channel / angle pairs is too small: is " + angles.length
                    + ", should be " + (nbChannels * 3)));
        }

        ByteBuffer paramsConverter = ByteBuffer.allocate(3 /* param + mask + device*/ * 4);
        paramsConverter.order(ByteOrder.nativeOrder());
        paramsConverter.putInt(PARAM_VIRTUAL_SPEAKER_ANGLES);
        // convert channel mask to internal native representation
        paramsConverter.putInt(AudioFormat.convertChannelOutMaskToNativeMask(channelMask));
        // convert Java device type to internal representation
        paramsConverter.putInt(AudioDeviceInfo.convertDeviceTypeToInternalDevice(deviceType));
        // allocate an array to store the results
        byte[] result = new byte[nbChannels * 4/*int to byte*/ * 3/*for mask, azimuth, elevation*/];

        // call into the effect framework
        int status = getParameter(paramsConverter.array(), result);
        if (DEBUG) {
            Log.v(TAG, "getAngles(0x" + Integer.toHexString(inputChannelMask) + ", 0x"
                    + Integer.toHexString(deviceType) + ") returns " + status);
        }

        if (status >= 0) {
            if (angles != null) {
                // convert and copy the results
                ByteBuffer resultConverter = ByteBuffer.wrap(result);
                resultConverter.order(ByteOrder.nativeOrder());
                for (int i = 0 ; i < nbChannels ; i++) {
                    // write the channel mask
                    angles[3 * i] = AudioFormat.convertNativeChannelMaskToOutMask(
                            resultConverter.getInt((i * 4 * 3)));
                    // write the azimuth
                    angles[3 * i + 1] = resultConverter.getInt(i * 4 * 3 + 4);
                    // write the elevation
                    angles[3 * i + 2] = resultConverter.getInt(i * 4 * 3 + 8);
                    if (DEBUG) {
                        Log.v(TAG, "channel 0x" + Integer.toHexString(angles[3*i]).toUpperCase()
                                + " at az=" + angles[3*i+1] + "deg"
                                + " elev="  + angles[3*i+2] + "deg");
                    }
                }
            }
            return true;
        } else if (status == AudioEffect.ERROR_BAD_VALUE) {
            // a BAD_VALUE return from getParameter indicates the configuration is not supported
            // don't throw an exception, just return false
            return false;
        } else {
            // something wrong may have happened
            checkStatus(status);
        }
        // unexpected virtualizer behavior
        Log.e(TAG, "unexpected status code " + status
                + " after getParameter(PARAM_VIRTUAL_SPEAKER_ANGLES)");
        return false;
    }

    /**
     * A virtualization mode indicating virtualization processing is not active.
     * See {@link #getVirtualizationMode()} as one of the possible return value.
     */
    public static final int VIRTUALIZATION_MODE_OFF = 0;

    /**
     * A virtualization mode used to indicate the virtualizer effect must stop forcing the
     * processing to a particular mode in {@link #forceVirtualizationMode(int)}.
     */
    public static final int VIRTUALIZATION_MODE_AUTO = 1;
    /**
     * A virtualization mode typically used over headphones.
     * Binaural virtualization describes an audio processing configuration for virtualization
     * where the left and right channels are respectively reaching the left and right ear of the
     * user, without also feeding the opposite ear (as is the case when listening over speakers).
     * <p>Such a mode is therefore meant to be used when audio is playing over stereo wired
     * headphones or headsets, but also stereo headphones through a wireless A2DP Bluetooth link.
     * <p>See {@link #canVirtualize(int, int)} to verify this mode is supported by this Virtualizer.
     */
    public final static int VIRTUALIZATION_MODE_BINAURAL = 2;

    /**
     * A virtualization mode typically used over speakers.
     * Transaural virtualization describes an audio processing configuration that differs from
     * binaural (as described in {@link #VIRTUALIZATION_MODE_BINAURAL} in that cross-talk is
     * present, i.e. audio played from the left channel also reaches the right ear of the user,
     * and vice-versa.
     * <p>When supported, such a mode is therefore meant to be used when audio is playing over the
     * built-in stereo speakers of a device, if they are featured.
     * <p>See {@link #canVirtualize(int, int)} to verify this mode is supported by this Virtualizer.
     */
    public final static int VIRTUALIZATION_MODE_TRANSAURAL = 3;

    /** @hide */
    @IntDef( {
        VIRTUALIZATION_MODE_BINAURAL,
        VIRTUALIZATION_MODE_TRANSAURAL
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface VirtualizationMode {}

    /** @hide */
    @IntDef( {
        VIRTUALIZATION_MODE_AUTO,
        VIRTUALIZATION_MODE_BINAURAL,
        VIRTUALIZATION_MODE_TRANSAURAL
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ForceVirtualizationMode {}

    private static int getDeviceForModeQuery(@VirtualizationMode int virtualizationMode)
            throws IllegalArgumentException {
        switch (virtualizationMode) {
            case VIRTUALIZATION_MODE_BINAURAL:
                return AudioDeviceInfo.TYPE_WIRED_HEADPHONES;
            case VIRTUALIZATION_MODE_TRANSAURAL:
                return AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;
            default:
                throw (new IllegalArgumentException(
                        "Virtualizer: illegal virtualization mode " + virtualizationMode));
        }
    }

    private static int getDeviceForModeForce(@ForceVirtualizationMode int virtualizationMode)
            throws IllegalArgumentException {
        if (virtualizationMode == VIRTUALIZATION_MODE_AUTO) {
            return AudioDeviceInfo.TYPE_UNKNOWN;
        } else {
            return getDeviceForModeQuery(virtualizationMode);
        }
    }

    private static int deviceToMode(int deviceType) {
        switch (deviceType) {
            case AudioDeviceInfo.TYPE_WIRED_HEADSET:
            case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
            case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
            case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
            case AudioDeviceInfo.TYPE_USB_HEADSET:
                return VIRTUALIZATION_MODE_BINAURAL;
            case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
            case AudioDeviceInfo.TYPE_LINE_ANALOG:
            case AudioDeviceInfo.TYPE_LINE_DIGITAL:
            case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
            case AudioDeviceInfo.TYPE_HDMI:
            case AudioDeviceInfo.TYPE_HDMI_ARC:
            case AudioDeviceInfo.TYPE_USB_DEVICE:
            case AudioDeviceInfo.TYPE_USB_ACCESSORY:
            case AudioDeviceInfo.TYPE_DOCK:
            case AudioDeviceInfo.TYPE_FM:
            case AudioDeviceInfo.TYPE_AUX_LINE:
                return VIRTUALIZATION_MODE_TRANSAURAL;
            case AudioDeviceInfo.TYPE_UNKNOWN:
            default:
                return VIRTUALIZATION_MODE_OFF;
        }
    }

    /**
     * Checks if the combination of a channel mask and virtualization mode is supported by this
     * virtualizer.
     * Some virtualizer implementations may only support binaural processing (i.e. only support
     * headphone output, see {@link #VIRTUALIZATION_MODE_BINAURAL}), some may support transaural
     * processing (i.e. for speaker output, see {@link #VIRTUALIZATION_MODE_TRANSAURAL}) for the
     * built-in speakers. Use this method to query the virtualizer implementation capabilities.
     * @param inputChannelMask the channel mask of the content to virtualize.
     * @param virtualizationMode the mode for which virtualization processing is to be performed,
     *    one of {@link #VIRTUALIZATION_MODE_BINAURAL}, {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
     * @return true if the combination of channel mask and virtualization mode is supported, false
     *    otherwise.
     *    <br>An indication that a certain channel mask is not supported doesn't necessarily mean
     *    you cannot play content with that channel mask, it more likely implies the content will
     *    be downmixed before being virtualized. For instance a virtualizer that only supports a
     *    mask such as {@link AudioFormat#CHANNEL_OUT_STEREO}
     *    will still be able to process content with a mask of
     *    {@link AudioFormat#CHANNEL_OUT_5POINT1}, but will downmix the content to stereo first, and
     *    then will virtualize, as opposed to virtualizing each channel individually.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public boolean canVirtualize(int inputChannelMask, @VirtualizationMode int virtualizationMode)
            throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        return getAnglesInt(inputChannelMask, getDeviceForModeQuery(virtualizationMode), null);
    }

    /**
     * Queries the virtual speaker angles (azimuth and elevation) for a combination of a channel
     * mask and virtualization mode.
     * If the virtualization configuration (mask and mode) is supported (see
     * {@link #canVirtualize(int, int)}, the array angles will contain upon return the
     * definition of each virtual speaker and its azimuth and elevation angles relative to the
     * listener.
     * <br>Note that in some virtualizer implementations, the angles may be strength-dependent.
     * @param inputChannelMask the channel mask of the content to virtualize.
     * @param virtualizationMode the mode for which virtualization processing is to be performed,
     *    one of {@link #VIRTUALIZATION_MODE_BINAURAL}, {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
     * @param angles a non-null array whose length is 3 times the number of channels in the channel
     *    mask.
     *    If the method indicates the configuration is supported, the array will contain upon return
     *    triplets of values: for each channel <code>i</code> among the channels of the mask:
     *    <ul>
     *      <li>the element at index <code>3*i</code> in the array contains the speaker
     *          identification (e.g. {@link AudioFormat#CHANNEL_OUT_FRONT_LEFT}),</li>
     *      <li>the element at index <code>3*i+1</code> contains its corresponding azimuth angle
     *          expressed in degrees, where 0 is the direction the listener faces, 180 is behind
     *          the listener, and -90 is to her/his left,</li>
     *      <li>the element at index <code>3*i+2</code> contains its corresponding elevation angle
     *          where +90 is directly above the listener, 0 is the horizontal plane, and -90 is
     *          directly below the listener.</li>
     * @return true if the combination of channel mask and virtualization mode is supported, false
     *    otherwise.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public boolean getSpeakerAngles(int inputChannelMask,
            @VirtualizationMode int virtualizationMode, int[] angles)
            throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        if (angles == null) {
            throw (new IllegalArgumentException(
                    "Virtualizer: illegal null channel / angle array"));
        }

        return getAnglesInt(inputChannelMask, getDeviceForModeQuery(virtualizationMode), angles);
    }

    /**
     * Forces the virtualizer effect to use the given processing mode.
     * The effect must be enabled for the forced mode to be applied.
     * @param virtualizationMode one of {@link #VIRTUALIZATION_MODE_BINAURAL},
     *     {@link #VIRTUALIZATION_MODE_TRANSAURAL} to force a particular processing mode, or
     *     {@value #VIRTUALIZATION_MODE_AUTO} to stop forcing a mode.
     * @return true if the processing mode is supported, and it is successfully set, or
     *     forcing was successfully disabled, false otherwise.
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public boolean forceVirtualizationMode(@ForceVirtualizationMode int virtualizationMode)
            throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        // convert Java device type to internal representation
        int deviceType = getDeviceForModeForce(virtualizationMode);
        int internalDevice = AudioDeviceInfo.convertDeviceTypeToInternalDevice(deviceType);

        int status = setParameter(PARAM_FORCE_VIRTUALIZATION_MODE, internalDevice);

        if (status >= 0) {
            return true;
        } else if (status == AudioEffect.ERROR_BAD_VALUE) {
            // a BAD_VALUE return from setParameter indicates the mode can't be forced
            // don't throw an exception, just return false
            return false;
        } else {
            // something wrong may have happened
            checkStatus(status);
        }
        // unexpected virtualizer behavior
        Log.e(TAG, "unexpected status code " + status
                + " after setParameter(PARAM_FORCE_VIRTUALIZATION_MODE)");
        return false;
    }

    /**
     * Return the virtualization mode being used, if any.
     * @return the virtualization mode being used.
     *     If virtualization is not active, the virtualization mode will be
     *     {@link #VIRTUALIZATION_MODE_OFF}. Otherwise the value will be
     *     {@link #VIRTUALIZATION_MODE_BINAURAL} or {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
     *     Virtualization may not be active either because the effect is not enabled or
     *     because the current output device is not compatible with this virtualization
     *     implementation.
     * @throws IllegalStateException
     * @throws UnsupportedOperationException
     */
    public int getVirtualizationMode()
            throws IllegalStateException, UnsupportedOperationException {
        int[] value = new int[1];
        int status = getParameter(PARAM_VIRTUALIZATION_MODE, value);
        if (status >= 0) {
            return deviceToMode(AudioDeviceInfo.convertInternalDeviceToDeviceType(value[0]));
        } else if (status == AudioEffect.ERROR_BAD_VALUE) {
            return VIRTUALIZATION_MODE_OFF;
        } else {
            // something wrong may have happened
            checkStatus(status);
        }
        // unexpected virtualizer behavior
        Log.e(TAG, "unexpected status code " + status
                + " after getParameter(PARAM_VIRTUALIZATION_MODE)");
        return VIRTUALIZATION_MODE_OFF;
    }

    /**
     * The OnParameterChangeListener interface defines a method called by the Virtualizer 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
         * Virtualizer engine.
         * @param effect the Virtualizer on which the interface is registered.
         * @param status status of the set parameter operation.
         * @param param ID of the modified parameter. See {@link #PARAM_STRENGTH} ...
         * @param value the new parameter value.
         */
        void onParameterChange(Virtualizer effect, int status, int param, short 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 p = -1;
                short v = -1;

                if (param.length == 4) {
                    p = byteArrayToInt(param, 0);
                }
                if (value.length == 2) {
                    v = byteArrayToShort(value, 0);
                }
                if (p != -1 && v != -1) {
                    l.onParameterChange(Virtualizer.this, status, p, 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 virtualizer 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 strength;

        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() != 3) {
                throw new IllegalArgumentException("settings: " + settings);
            }
            String key = st.nextToken();
            if (!key.equals("Virtualizer")) {
                throw new IllegalArgumentException(
                        "invalid settings for Virtualizer: " + key);
            }
            try {
                key = st.nextToken();
                if (!key.equals("strength")) {
                    throw new IllegalArgumentException("invalid key name: " + key);
                }
                strength = Short.parseShort(st.nextToken());
             } catch (NumberFormatException nfe) {
                throw new IllegalArgumentException("invalid value for key: " + key);
            }
        }

        @Override
        public String toString() {
            String str = new String (
                    "Virtualizer"+
                    ";strength="+Short.toString(strength)
                    );
            return str;
        }
    };


    /**
     * Gets the virtualizer properties. This method is useful when a snapshot of current
     * virtualizer settings must be saved by the application.
     * @return a Virtualizer.Settings object containing all current parameters values
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public Virtualizer.Settings getProperties()
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        Settings settings = new Settings();
        short[] value = new short[1];
        checkStatus(getParameter(PARAM_STRENGTH, value));
        settings.strength = value[0];
        return settings;
    }

    /**
     * Sets the virtualizer properties. This method is useful when virtualizer settings have to
     * be applied from a previous backup.
     * @param settings a Virtualizer.Settings object containing the properties to apply
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @throws UnsupportedOperationException
     */
    public void setProperties(Virtualizer.Settings settings)
    throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
        checkStatus(setParameter(PARAM_STRENGTH, settings.strength));
    }
}
