/*
 * 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.
 */

/** \file OpenSLESUT.c OpenSL ES Utility Toolkit */

#include "SLES/OpenSLES.h"
#ifdef ANDROID
#include "SLES/OpenSLES_Android.h"
#endif
#include "OpenSLESUT.h"
#include <stdio.h>
#include <string.h>

/** \brief Array of strings correponding to each result code */

const char * const slesutResultStrings[SLESUT_RESULT_MAX] = {
    "SUCCESS",
    "PRECONDITIONS_VIOLATED",
    "PARAMETER_INVALID",
    "MEMORY_FAILURE",
    "RESOURCE_ERROR",
    "RESOURCE_LOST",
    "IO_ERROR",
    "BUFFER_INSUFFICIENT",
    "CONTENT_CORRUPTED",
    "CONTENT_UNSUPPORTED",
    "CONTENT_NOT_FOUND",
    "PERMISSION_DENIED",
    "FEATURE_UNSUPPORTED",
    "INTERNAL_ERROR",
    "UNKNOWN_ERROR",
    "OPERATION_ABORTED",
    "CONTROL_LOST"
};

/** \brief Maps an interface ID to its display name */

typedef struct
{
    const SLInterfaceID *iid;   ///< The interface ID
    const char *name;           ///< The display name
} Pair;

// ## is token concatenation e.g. a##b becomes ab
// # is stringize operator to convert a symbol to a string constant e.g. #a becomes "a"

#define _(x) { &SL_IID_##x, #x }

/** \brief Array of mappings from interface IDs to display names */

static Pair pairs[] = {
    _(3DCOMMIT),
    _(3DDOPPLER),
    _(3DGROUPING),
    _(3DLOCATION),
    _(3DMACROSCOPIC),
    _(3DSOURCE),
    _(AUDIODECODERCAPABILITIES),
    _(AUDIOENCODER),
    _(AUDIOENCODERCAPABILITIES),
    _(AUDIOIODEVICECAPABILITIES),
    _(BASSBOOST),
    _(BUFFERQUEUE),
    _(DEVICEVOLUME),
    _(DYNAMICINTERFACEMANAGEMENT),
    _(DYNAMICSOURCE),
    _(EFFECTSEND),
    _(ENGINE),
    _(ENGINECAPABILITIES),
    _(ENVIRONMENTALREVERB),
    _(EQUALIZER),
    _(LED),
    _(METADATAEXTRACTION),
    _(METADATATRAVERSAL),
    _(MIDIMESSAGE),
    _(MIDIMUTESOLO),
    _(MIDITEMPO),
    _(MIDITIME),
    _(MUTESOLO),
    _(NULL),
    _(OBJECT),
    _(OUTPUTMIX),
    _(PITCH),
    _(PLAY),
    _(PLAYBACKRATE),
    _(PREFETCHSTATUS),
    _(PRESETREVERB),
    _(RATEPITCH),
    _(RECORD),
    _(SEEK),
    _(THREADSYNC),
    _(VIBRA),
    _(VIRTUALIZER),
    _(VISUALIZATION),
    _(VOLUME),
#if 0 // ifdef USE_OUTPUTMIXEXT
    _(OUTPUTMIXEXT),
#endif
#ifdef ANDROID
    _(ANDROIDEFFECT),
    _(ANDROIDEFFECTCAPABILITIES),
    _(ANDROIDEFFECTSEND),
    _(ANDROIDCONFIGURATION),
    _(ANDROIDSIMPLEBUFFERQUEUE)
#endif
};

/** \brief Print an interface ID in human-readable format */

void slesutPrintIID(SLInterfaceID iid)
{
    Pair *p;
    const Pair *end = &pairs[sizeof(pairs)/sizeof(pairs[0])];
    for (p = pairs; p != end; ++p) {
        if (!memcmp(*p->iid, iid, sizeof(struct SLInterfaceID_))) {
            printf("SL_IID_%s = ", p->name);
            break;
        }
    }
    printf(
        "{ 0x%08X, 0x%04X, 0x%04X, 0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n",
        (unsigned) iid->time_low, iid->time_mid, iid->time_hi_and_version, iid->clock_seq,
        iid->node[0], iid->node[1], iid->node[2], iid->node[3], iid->node[4], iid->node[5]);
}

/** \brief Print an array of interface IDs in human-readable format,
 *  including whether they are required or optional
 */

void slesutPrintIIDs(SLInterfaceID *pInterfaceIds, SLboolean *pInterfaceRequired,
    unsigned numInterfaces)
{
    unsigned i;
    for (i = 0; i < numInterfaces; ++i) {
        printf("interfaces[%u]=", i);
        slesutPrintIID(pInterfaceIds[i]);
        printf(" %s\n", (unsigned) pInterfaceRequired[i] ? "required" : "optional");
    }
}


/** \brief Convert a result code to a string. */

const char *slesutResultToString(SLresult result)
{
    // note that SLresult is unsigned
    return result < SLESUT_RESULT_MAX ? slesutResultStrings[result] : "UNKNOWN";
}
