/*
 * Copyright (C) 2014 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;

import android.annotation.UnsupportedAppUsage;

/**
 * An audio port is a node of the audio framework or hardware that can be connected to or
 * disconnect from another audio node to create a specific audio routing configuration.
 * Examples of audio ports are an output device (speaker) or an output mix (see AudioMixPort).
 * All attributes that are relevant for applications to make routing selection are described
 * in an AudioPort,  in particular:
 * - possible channel mask configurations.
 * - audio format (PCM 16bit, PCM 24bit...)
 * - gain: a port can be associated with one or more gain controllers (see AudioGain).
 *
 * This object is always created by the framework and read only by applications.
 * A list of all audio port descriptors currently available for applications to control
 * is obtained by AudioManager.listAudioPorts().
 * An application can obtain an AudioPortConfig for a valid configuration of this port
 * by calling AudioPort.buildConfig() and use this configuration
 * to create a connection between audio sinks and sources with AudioManager.connectAudioPatch()
 *
 * @hide
 */
public class AudioPort {
    private static final String TAG = "AudioPort";

    /**
     * For use by the audio framework.
     */
    public static final int ROLE_NONE = 0;
    /**
     * The audio port is a source (produces audio)
     */
    public static final int ROLE_SOURCE = 1;
    /**
     * The audio port is a sink (consumes audio)
     */
    public static final int ROLE_SINK = 2;

    /**
     * audio port type for use by audio framework implementation
     */
    public static final int TYPE_NONE = 0;
    /**
     */
    public static final int TYPE_DEVICE = 1;
    /**
     */
    public static final int TYPE_SUBMIX = 2;
    /**
     */
    public static final int TYPE_SESSION = 3;


    @UnsupportedAppUsage
    AudioHandle mHandle;
    @UnsupportedAppUsage
    protected final int mRole;
    private final String mName;
    private final int[] mSamplingRates;
    private final int[] mChannelMasks;
    private final int[] mChannelIndexMasks;
    private final int[] mFormats;
    @UnsupportedAppUsage
    private final AudioGain[] mGains;
    @UnsupportedAppUsage
    private AudioPortConfig mActiveConfig;

    @UnsupportedAppUsage
    AudioPort(AudioHandle handle, int role, String name,
            int[] samplingRates, int[] channelMasks, int[] channelIndexMasks,
            int[] formats, AudioGain[] gains) {

        mHandle = handle;
        mRole = role;
        mName = name;
        mSamplingRates = samplingRates;
        mChannelMasks = channelMasks;
        mChannelIndexMasks = channelIndexMasks;
        mFormats = formats;
        mGains = gains;
    }

    AudioHandle handle() {
        return mHandle;
    }

    /**
     * Get the system unique device ID.
     */
    @UnsupportedAppUsage
    public int id() {
        return mHandle.id();
    }


    /**
     * Get the audio port role
     */
    @UnsupportedAppUsage
    public int role() {
        return mRole;
    }

    /**
     * Get the human-readable name of this port. Perhaps an internal
     * designation or an physical device.
     */
    public String name() {
        return mName;
    }

    /**
     * Get the list of supported sampling rates
     * Empty array if sampling rate is not relevant for this audio port
     */
    public int[] samplingRates() {
        return mSamplingRates;
    }

    /**
     * Get the list of supported channel mask configurations
     * (e.g AudioFormat.CHANNEL_OUT_STEREO)
     * Empty array if channel mask is not relevant for this audio port
     */
    public int[] channelMasks() {
        return mChannelMasks;
    }

    /**
     * Get the list of supported channel index mask configurations
     * (e.g 0x0003 means 2 channel, 0x000F means 4 channel....)
     * Empty array if channel index mask is not relevant for this audio port
     */
    public int[] channelIndexMasks() {
        return mChannelIndexMasks;
    }

    /**
     * Get the list of supported audio format configurations
     * (e.g AudioFormat.ENCODING_PCM_16BIT)
     * Empty array if format is not relevant for this audio port
     */
    public int[] formats() {
        return mFormats;
    }

    /**
     * Get the list of gain descriptors
     * Empty array if this port does not have gain control
     */
    public AudioGain[] gains() {
        return mGains;
    }

    /**
     * Get the gain descriptor at a given index
     */
    AudioGain gain(int index) {
        if (index < 0 || index >= mGains.length) {
            return null;
        }
        return mGains[index];
    }

    /**
     * Build a specific configuration of this audio port for use by methods
     * like AudioManager.connectAudioPatch().
     * @param samplingRate
     * @param channelMask The desired channel mask. AudioFormat.CHANNEL_OUT_DEFAULT if no change
     * from active configuration requested.
     * @param format The desired audio format. AudioFormat.ENCODING_DEFAULT if no change
     * from active configuration requested.
     * @param gain The desired gain. null if no gain changed requested.
     */
    public AudioPortConfig buildConfig(int samplingRate, int channelMask, int format,
                                        AudioGainConfig gain) {
        return new AudioPortConfig(this, samplingRate, channelMask, format, gain);
    }

    /**
     * Get currently active configuration of this audio port.
     */
    public AudioPortConfig activeConfig() {
        return mActiveConfig;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || !(o instanceof AudioPort)) {
            return false;
        }
        AudioPort ap = (AudioPort)o;
        return mHandle.equals(ap.handle());
    }

    @Override
    public int hashCode() {
        return mHandle.hashCode();
    }

    @Override
    public String toString() {
        String role = Integer.toString(mRole);
        switch (mRole) {
            case ROLE_NONE:
                role = "NONE";
                break;
            case ROLE_SOURCE:
                role = "SOURCE";
                break;
            case ROLE_SINK:
                role = "SINK";
                break;
        }
        return "{mHandle: " + mHandle
                + ", mRole: " + role
                + "}";
    }
}
