/*
 * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

#define USE_ERROR
//#define USE_TRACE

#include "Ports.h"
#include "PLATFORM_API_SolarisOS_Utils.h"

#if USE_PORTS == TRUE

#define MONITOR_GAIN_STRING "Monitor Gain"

#define ALL_TARGET_PORT_COUNT 6

// define the following to not use audio_prinfo_t.mod_ports
#define SOLARIS7_COMPATIBLE

// Solaris audio defines
static int targetPorts[ALL_TARGET_PORT_COUNT] = {
    AUDIO_SPEAKER,
    AUDIO_HEADPHONE,
    AUDIO_LINE_OUT,
    AUDIO_AUX1_OUT,
    AUDIO_AUX2_OUT,
    AUDIO_SPDIF_OUT
};

static char* targetPortNames[ALL_TARGET_PORT_COUNT] = {
    "Speaker",
    "Headphone",
    "Line Out",
    "AUX1 Out",
    "AUX2 Out",
    "SPDIF Out"
};

// defined in Ports.h
static int targetPortJavaSoundMapping[ALL_TARGET_PORT_COUNT] = {
    PORT_DST_SPEAKER,
    PORT_DST_HEADPHONE,
    PORT_DST_LINE_OUT,
    PORT_DST_UNKNOWN,
    PORT_DST_UNKNOWN,
    PORT_DST_UNKNOWN,
};

#define ALL_SOURCE_PORT_COUNT 7

// Solaris audio defines
static int sourcePorts[ALL_SOURCE_PORT_COUNT] = {
    AUDIO_MICROPHONE,
    AUDIO_LINE_IN,
    AUDIO_CD,
    AUDIO_AUX1_IN,
    AUDIO_AUX2_IN,
    AUDIO_SPDIF_IN,
    AUDIO_CODEC_LOOPB_IN
};

static char* sourcePortNames[ALL_SOURCE_PORT_COUNT] = {
    "Microphone In",
    "Line In",
    "Compact Disc In",
    "AUX1 In",
    "AUX2 In",
    "SPDIF In",
    "Internal Loopback"
};

// Ports.h defines
static int sourcePortJavaSoundMapping[ALL_SOURCE_PORT_COUNT] = {
    PORT_SRC_MICROPHONE,
    PORT_SRC_LINE_IN,
    PORT_SRC_COMPACT_DISC,
    PORT_SRC_UNKNOWN,
    PORT_SRC_UNKNOWN,
    PORT_SRC_UNKNOWN,
    PORT_SRC_UNKNOWN
};

struct tag_PortControlID;

typedef struct tag_PortInfo {
    int fd;                    // file descriptor of the pseudo device
    audio_info_t audioInfo;
    // ports
    int targetPortCount;
    int sourcePortCount;
    // indexes to sourcePorts/targetPorts
    // contains first target ports, then source ports
    int ports[ALL_TARGET_PORT_COUNT + ALL_SOURCE_PORT_COUNT];
    // controls
    int maxControlCount;       // upper bound of number of controls
    int usedControlIDs;        // number of items already filled in controlIDs
    struct tag_PortControlID* controlIDs; // the control IDs themselves
} PortInfo;

#define PORT_CONTROL_TYPE_PLAY          0x4000000
#define PORT_CONTROL_TYPE_RECORD        0x8000000
#define PORT_CONTROL_TYPE_SELECT_PORT   1
#define PORT_CONTROL_TYPE_GAIN          2
#define PORT_CONTROL_TYPE_BALANCE       3
#define PORT_CONTROL_TYPE_MONITOR_GAIN  10
#define PORT_CONTROL_TYPE_OUTPUT_MUTED  11
#define PORT_CONTROL_TYPE_PLAYRECORD_MASK PORT_CONTROL_TYPE_PLAY | PORT_CONTROL_TYPE_RECORD
#define PORT_CONTROL_TYPE_MASK 0xFFFFFF


typedef struct tag_PortControlID {
    PortInfo*  portInfo;
    INT32                 controlType;  // PORT_CONTROL_TYPE_XX
    uint_t                port;
} PortControlID;


///// implemented functions of Ports.h

INT32 PORT_GetPortMixerCount() {
    return (INT32) getAudioDeviceCount();
}


INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
    AudioDeviceDescription desc;

    if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
        strncpy(description->name, desc.name, PORT_STRING_LENGTH-1);
        description->name[PORT_STRING_LENGTH-1] = 0;
        strncpy(description->vendor, desc.vendor, PORT_STRING_LENGTH-1);
        description->vendor[PORT_STRING_LENGTH-1] = 0;
        strncpy(description->version, desc.version, PORT_STRING_LENGTH-1);
        description->version[PORT_STRING_LENGTH-1] = 0;
        /*strncpy(description->description, desc.description, PORT_STRING_LENGTH-1);*/
        strncpy(description->description, "Solaris Ports", PORT_STRING_LENGTH-1);
        description->description[PORT_STRING_LENGTH-1] = 0;
        return TRUE;
    }
    return FALSE;
}


void* PORT_Open(INT32 mixerIndex) {
    PortInfo* info = NULL;
    int fd = -1;
    AudioDeviceDescription desc;
    int success = FALSE;

    TRACE0("PORT_Open\n");
    if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
        fd = open(desc.pathctl, O_RDWR);
    }
    if (fd < 0) {
        ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
        return NULL;
    }

    info = (PortInfo*) malloc(sizeof(PortInfo));
    if (info != NULL) {
        memset(info, 0, sizeof(PortInfo));
        info->fd = fd;
        success = TRUE;
    }
    if (!success) {
        if (fd >= 0) {
            close(fd);
        }
        PORT_Close((void*) info);
        info = NULL;
    }
    return info;
}

void PORT_Close(void* id) {
    TRACE0("PORT_Close\n");
    if (id != NULL) {
        PortInfo* info = (PortInfo*) id;
        if (info->fd >= 0) {
            close(info->fd);
            info->fd = -1;
        }
        if (info->controlIDs) {
            free(info->controlIDs);
            info->controlIDs = NULL;
        }
        free(info);
    }
}



INT32 PORT_GetPortCount(void* id) {
    int ret = 0;
    PortInfo* info = (PortInfo*) id;
    if (info != NULL) {
        if (!info->targetPortCount && !info->sourcePortCount) {
            int i;
            AUDIO_INITINFO(&info->audioInfo);
            if (ioctl(info->fd, AUDIO_GETINFO, &info->audioInfo) >= 0) {
                for (i = 0; i < ALL_TARGET_PORT_COUNT; i++) {
                    if (info->audioInfo.play.avail_ports & targetPorts[i]) {
                        info->ports[info->targetPortCount] = i;
                        info->targetPortCount++;
                    }
#ifdef SOLARIS7_COMPATIBLE
                    TRACE3("Target %d %s: avail=%d\n", i, targetPortNames[i],
                           info->audioInfo.play.avail_ports & targetPorts[i]);
#else
                    TRACE4("Target %d %s: avail=%d  mod=%d\n", i, targetPortNames[i],
                           info->audioInfo.play.avail_ports & targetPorts[i],
                           info->audioInfo.play.mod_ports & targetPorts[i]);
#endif
                }
                for (i = 0; i < ALL_SOURCE_PORT_COUNT; i++) {
                    if (info->audioInfo.record.avail_ports & sourcePorts[i]) {
                        info->ports[info->targetPortCount + info->sourcePortCount] = i;
                        info->sourcePortCount++;
                    }
#ifdef SOLARIS7_COMPATIBLE
                    TRACE3("Source %d %s: avail=%d\n", i, sourcePortNames[i],
                           info->audioInfo.record.avail_ports & sourcePorts[i]);
#else
                    TRACE4("Source %d %s: avail=%d  mod=%d\n", i, sourcePortNames[i],
                           info->audioInfo.record.avail_ports & sourcePorts[i],
                           info->audioInfo.record.mod_ports & sourcePorts[i]);
#endif
                }
            }
        }
        ret = info->targetPortCount + info->sourcePortCount;
    }
    return ret;
}

int isSourcePort(PortInfo* info, INT32 portIndex) {
    return (portIndex >= info->targetPortCount);
}

INT32 PORT_GetPortType(void* id, INT32 portIndex) {
    PortInfo* info = (PortInfo*) id;
    if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
        if (isSourcePort(info, portIndex)) {
            return sourcePortJavaSoundMapping[info->ports[portIndex]];
        } else {
            return targetPortJavaSoundMapping[info->ports[portIndex]];
        }
    }
    return 0;
}

// pre-condition: portIndex must have been verified!
char* getPortName(PortInfo* info, INT32 portIndex) {
    char* ret = NULL;

    if (isSourcePort(info, portIndex)) {
        ret = sourcePortNames[info->ports[portIndex]];
    } else {
        ret = targetPortNames[info->ports[portIndex]];
    }
    return ret;
}

INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
    PortInfo* info = (PortInfo*) id;
    char* n;

    if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
        n = getPortName(info, portIndex);
        if (n) {
            strncpy(name, n, len-1);
            name[len-1] = 0;
            return TRUE;
        }
    }
    return FALSE;
}

void createPortControl(PortInfo* info, PortControlCreator* creator, INT32 portIndex,
                       INT32 type, void** controlObjects, int* controlCount) {
    PortControlID* controlID;
    void* newControl = NULL;
    int controlIndex;
    char* jsType = NULL;
    int isBoolean = FALSE;

    TRACE0(">createPortControl\n");

    // fill the ControlID structure and add this control
    if (info->usedControlIDs >= info->maxControlCount) {
        ERROR1("not enough free controlIDs !! maxControlIDs = %d\n", info->maxControlCount);
        return;
    }
    controlID = &(info->controlIDs[info->usedControlIDs]);
    controlID->portInfo = info;
    controlID->controlType = type;
    controlIndex = info->ports[portIndex];
    if (isSourcePort(info, portIndex)) {
        controlID->port = sourcePorts[controlIndex];
    } else {
        controlID->port = targetPorts[controlIndex];
    }
    switch (type & PORT_CONTROL_TYPE_MASK) {
    case PORT_CONTROL_TYPE_SELECT_PORT:
        jsType = CONTROL_TYPE_SELECT; isBoolean = TRUE; break;
    case PORT_CONTROL_TYPE_GAIN:
        jsType = CONTROL_TYPE_VOLUME;  break;
    case PORT_CONTROL_TYPE_BALANCE:
        jsType = CONTROL_TYPE_BALANCE; break;
    case PORT_CONTROL_TYPE_MONITOR_GAIN:
        jsType = CONTROL_TYPE_VOLUME; break;
    case PORT_CONTROL_TYPE_OUTPUT_MUTED:
        jsType = CONTROL_TYPE_MUTE; isBoolean = TRUE; break;
    }
    if (isBoolean) {
        TRACE0(" PORT_CONTROL_TYPE_BOOLEAN\n");
        newControl = (creator->newBooleanControl)(creator, controlID, jsType);
    }
    else if (jsType == CONTROL_TYPE_BALANCE) {
        TRACE0(" PORT_CONTROL_TYPE_BALANCE\n");
        newControl = (creator->newFloatControl)(creator, controlID, jsType,
                                                -1.0f, 1.0f, 2.0f / 65.0f, "");
    } else {
        TRACE0(" PORT_CONTROL_TYPE_FLOAT\n");
        newControl = (creator->newFloatControl)(creator, controlID, jsType,
                                                0.0f, 1.0f, 1.0f / 256.0f, "");
    }
    if (newControl) {
        controlObjects[*controlCount] = newControl;
        (*controlCount)++;
        info->usedControlIDs++;
    }
    TRACE0("<createPortControl\n");
}


void addCompoundControl(PortInfo* info, PortControlCreator* creator, char* name, void** controlObjects, int* controlCount) {
    void* compControl;

    TRACE1(">addCompoundControl %d controls\n", *controlCount);
    if (*controlCount) {
        // create compound control and add it to the vector
        compControl = (creator->newCompoundControl)(creator, name, controlObjects, *controlCount);
        if (compControl) {
            TRACE1(" addCompoundControl: calling addControl %p\n", compControl);
            (creator->addControl)(creator, compControl);
        }
        *controlCount = 0;
    }
    TRACE0("<addCompoundControl\n");
}

void addAllControls(PortInfo* info, PortControlCreator* creator, void** controlObjects, int* controlCount) {
    int i = 0;

    TRACE0(">addAllControl\n");
    // go through all controls and add them to the vector
    for (i = 0; i < *controlCount; i++) {
        (creator->addControl)(creator, controlObjects[i]);
    }
    *controlCount = 0;
    TRACE0("<addAllControl\n");
}

void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
    PortInfo* info = (PortInfo*) id;
    int portCount = PORT_GetPortCount(id);
    void* controls[4];
    int controlCount = 0;
    INT32 type;
    int selectable = 1;

    TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n",
           id, portIndex, info->controlIDs, info->maxControlCount);
    if ((portIndex >= 0) && (portIndex < portCount)) {
        // if the memory isn't reserved for the control structures, allocate it
        if (!info->controlIDs) {
            int maxCount = 0;
            TRACE0("getControl: allocate mem\n");
            // get a maximum number of controls:
            // each port has a select, balance, and volume control.
            maxCount = 3 * portCount;
            // then there is monitorGain and outputMuted
            maxCount += (2 * info->targetPortCount);
            info->maxControlCount = maxCount;
            info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount);
        }
        if (!isSourcePort(info, portIndex)) {
            type = PORT_CONTROL_TYPE_PLAY;
            // add master mute control
            createPortControl(info, creator, portIndex,
                              type | PORT_CONTROL_TYPE_OUTPUT_MUTED,
                              controls, &controlCount);
            addAllControls(info, creator, controls, &controlCount);
#ifdef SOLARIS7_COMPATIBLE
            selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]];
#else
            selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]];
#endif
        } else {
            type = PORT_CONTROL_TYPE_RECORD;
#ifdef SOLARIS7_COMPATIBLE
            selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]];
#else
            selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]];
#endif
        }
        // add a mixer strip with volume, ...
        createPortControl(info, creator, portIndex,
                          type | PORT_CONTROL_TYPE_GAIN,
                          controls, &controlCount);
        // ... balance, ...
        createPortControl(info, creator, portIndex,
                          type | PORT_CONTROL_TYPE_BALANCE,
                          controls, &controlCount);
        // ... and select control (if not always on)...
        if (selectable) {
            createPortControl(info, creator, portIndex,
                              type | PORT_CONTROL_TYPE_SELECT_PORT,
                              controls, &controlCount);
        }
        // ... packaged in a compound control.
        addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount);

        if (type == PORT_CONTROL_TYPE_PLAY) {
            // add a single strip for source ports with monitor gain
            createPortControl(info, creator, portIndex,
                              type | PORT_CONTROL_TYPE_MONITOR_GAIN,
                              controls, &controlCount);
            // also in a compound control
            addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount);
        }
    }
    TRACE0("< PORT_getControls\n");
}

INT32 PORT_GetIntValue(void* controlIDV) {
    PortControlID* controlID = (PortControlID*) controlIDV;
    audio_info_t audioInfo;
    audio_prinfo_t* prinfo;

    AUDIO_INITINFO(&audioInfo);
    if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
        if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
            prinfo = &(audioInfo.play);
        } else {
            prinfo = &(audioInfo.record);
        }
        switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
        case PORT_CONTROL_TYPE_SELECT_PORT:
            return (prinfo->port & controlID->port)?TRUE:FALSE;
        case PORT_CONTROL_TYPE_OUTPUT_MUTED:
            return (audioInfo.output_muted)?TRUE:FALSE;
        default:
            ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
        }
    }
    ERROR0("PORT_GetIntValue: Could not ioctl!\n");
    return 0;
}

void PORT_SetIntValue(void* controlIDV, INT32 value) {
    PortControlID* controlID = (PortControlID*) controlIDV;
    audio_info_t audioInfo;
    audio_prinfo_t* prinfo;
    int setPort;

    if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
        prinfo = &(audioInfo.play);
    } else {
        prinfo = &(audioInfo.record);
    }
    switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
    case PORT_CONTROL_TYPE_SELECT_PORT:
        // first try to just add this port. if that fails, set ONLY to this port.
        AUDIO_INITINFO(&audioInfo);
        if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
            if (value) {
                setPort = (prinfo->port | controlID->port);
            } else {
                setPort = (prinfo->port - controlID->port);
            }
            AUDIO_INITINFO(&audioInfo);
            prinfo->port = setPort;
            if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
                // didn't work. Either this line doesn't support to select several
                // ports at once (e.g. record), or a real error
                if (value) {
                    // set to ONLY this port (and disable any other currently selected ports)
                    AUDIO_INITINFO(&audioInfo);
                    prinfo->port = controlID->port;
                    if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
                        ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port);
                    }
                } else {
                    // assume it's an error
                    ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort);
                }
            }
            break;
        case PORT_CONTROL_TYPE_OUTPUT_MUTED:
            AUDIO_INITINFO(&audioInfo);
            audioInfo.output_muted = (value?TRUE:FALSE);
            if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
                ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value);
            }
            break;
        default:
            ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
        }
    }
}

float PORT_GetFloatValue(void* controlIDV) {
    PortControlID* controlID = (PortControlID*) controlIDV;
    audio_info_t audioInfo;
    audio_prinfo_t* prinfo;

    AUDIO_INITINFO(&audioInfo);
    if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
        if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
            prinfo = &(audioInfo.play);
        } else {
            prinfo = &(audioInfo.record);
        }
        switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
        case PORT_CONTROL_TYPE_GAIN:
            return ((float) (prinfo->gain - AUDIO_MIN_GAIN))
                / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
        case PORT_CONTROL_TYPE_BALANCE:
            return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1))
                / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE));
        case PORT_CONTROL_TYPE_MONITOR_GAIN:
            return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN))
                / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
        default:
            ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
        }
    }
    ERROR0("PORT_GetFloatValue: Could not ioctl!\n");
    return 0.0f;
}

void PORT_SetFloatValue(void* controlIDV, float value) {
    PortControlID* controlID = (PortControlID*) controlIDV;
    audio_info_t audioInfo;
    audio_prinfo_t* prinfo;

    AUDIO_INITINFO(&audioInfo);

    if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
        prinfo = &(audioInfo.play);
    } else {
        prinfo = &(audioInfo.record);
    }
    switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
    case PORT_CONTROL_TYPE_GAIN:
        prinfo->gain = AUDIO_MIN_GAIN
            + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
        break;
    case PORT_CONTROL_TYPE_BALANCE:
        prinfo->balance =  AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE
            + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f);
        break;
    case PORT_CONTROL_TYPE_MONITOR_GAIN:
        audioInfo.monitor_gain = AUDIO_MIN_GAIN
            + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
        break;
    default:
        ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
        return;
    }
    if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
        ERROR0("PORT_SetFloatValue: Could not ioctl!\n");
    }
}

#endif // USE_PORTS
