/*
 * Copyright (C) 2010 Motorola
 * Copyright (C) 2011-2012 Canonical, Ltd.
 *
 * 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.
 */

#define LOG_NDEBUG 0
#define LOG_TAG "AndroidAudioWrapper"

#include <waudio/android_audio_wrapper_define.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <stdio.h>
#include "media/AudioTrack.h"
#include "media/AudioRecord.h"
#include "media/AudioSystem.h"
using namespace android;

extern "C"
{

TrackHandle CreateAudioTrack()
{
    ALOGV("Enter CreateAudioTrack");
    AudioTrack* lpTrack = new AudioTrack();

    if (lpTrack == NULL)
    {
        ALOGV("Error creating uninitialized AudioTrack");
        return NULL;
    }
    ALOGV("create AudioTrack successfully");
    return (TrackHandle)lpTrack;
}

status_type AudioTrack_set(TrackHandle handle, audio_stream_type_t streamtype,
                uint32 samplerate, audio_format_t format,
                audio_channel_mask_t channel)
{
    status_type result = INVALID_PARAM;
    status_t andrresult;

    ALOGV("Enter AudioTrack_set and streamtype is %d, samplerate is %d, audioformat is %d, audiochannels is %d.",
                (int) streamtype, (int) samplerate, (int) format, (int) channel);

    if (handle != NULL)
    {
        andrresult = static_cast<AudioTrack*>(handle)->set(streamtype,
                        samplerate, format, channel);
        result = (status_type) andrresult;
        ALOGV("Call AudioTrack set and result is %d", andrresult);
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioTrack set");
    }
    return result;
}

status_type AudioTrack_set_asyn(TrackHandle handle, audio_stream_type_t streamtype,
                uint32 samplerate, audio_format_t format,
                audio_channel_mask_t channel, callback_t cbf, void* user)
{
    status_type result = INVALID_PARAM;
    status_t andrresult;

    ALOGV("Enter AudioTrack_set and streamtype is %d, samplerate is %d, audioformat is %d, audiochannels is %d.",
                (int) streamtype, (int) samplerate, (int) format, (int) channel);

    if (handle != NULL)
    {
        andrresult = static_cast<AudioTrack*>(handle)->set(streamtype,
                        samplerate, format, channel, 0,
                        static_cast<audio_output_flags_t>(0), cbf, user);
        result = (status_type) andrresult;
        ALOGV("Call AudioTrack set and result is %d", andrresult);
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioTrack set asyn");
    }
    return result;
}

void AudioTrack_start(TrackHandle handle)
{
    ALOGV("Enter AudioTrack_start");
    if (handle != NULL)
        static_cast<AudioTrack*>(handle)->start();
    else
        ALOGV("Handle is invalid and does not call AudioTrack start");
}

void AudioTrack_stop(TrackHandle handle)
{
    ALOGV("Enter AudioTrack_stop");
    if (handle != NULL)
        static_cast<AudioTrack*>(handle)->stop();
    else
        ALOGV("Handle is invalid and does not call AudioTrack stop");
}

status_type AudioTrack_getposition(TrackHandle handle, uint32 *position)
{
    ALOGV("Enter AudioTrack_getposition");
    status_type result = INVALID_PARAM;
    status_t andrresult;

    if (handle != NULL && position != NULL)
    {
        andrresult = static_cast<AudioTrack*>(handle)->getPosition((uint32_t*) position);
        result = (status_type) andrresult;
        ALOGV("Call AudioTrack getPosition and result is %d, position=%d.",
                                        (int) andrresult, (int) *position);
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioTrack getPosition");
    }
    return result;
}

size_t AudioTrack_write(TrackHandle handle, const void *buffer, size_t size)
{
    ALOGV("Enter AudioTrack_write and size is %d.", size);
    size_t result = 0;

    if (handle != NULL && buffer != NULL && size > 0)
    {
        result = static_cast<AudioTrack*>(handle)->write(buffer, size);
        ALOGV("Call AudioTrack write and result is %d.", result);
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioTrack write");
    }
    return result;
}

void AudioTrack_pause(TrackHandle handle)
{
    ALOGV("Enter AudioTrack_pause");
    if (handle != NULL)
        static_cast<AudioTrack*>(handle)->pause();
    else
        ALOGV("Handle is invalid and does not call AudioTrack pause");
}

uint32 AudioTrack_latency(TrackHandle handle)
{
    ALOGV("Enter AudioTrack_latency");
    uint32 result = 0;
    if (handle != NULL)
        result = static_cast<AudioTrack*>(handle)->latency();
    else
        ALOGV("Handle is invalid and does not call AudioTrack latency");

    return result;
}

void AudioTrack_mute(TrackHandle handle, int muted)
{
    ALOGV("Enter AudioTrack_mute");
    if (handle != NULL)
        static_cast<AudioTrack*>(handle)->mute(muted);
    else
        ALOGV("Handle is invalid and does not call AudioTrack mute");
}

void DestoryAudioTrack(TrackHandle handle)
{
    ALOGV("Enter DestoryAudioTrack");
    if (handle != NULL)
    {
        delete static_cast<AudioTrack*>(handle);
        ALOGV("Delete AudioTrack successfully");
    }
    else
    {
        ALOGV("Handle is invalid and does not delete AudioTrack");
    }
}

/* Audio Record related interface */
RecordHandle CreateAudioRecord()
{
    ALOGV("Enter CreateAudioRecord");
    AudioRecord* lpRecord = new AudioRecord();

    if (lpRecord == NULL)
    {
        ALOGV("Error creating uninitialized AudioRecord");
        return NULL;
    }
    ALOGV("create AudioRecord successfully");
    return (RecordHandle) lpRecord;
}

void DestoryAudioRecord(RecordHandle handle)
{
    ALOGV("Enter DestoryAudioRecord");
    if (handle != NULL )
    {
        delete static_cast<AudioTrack*>(handle);
        ALOGV("Delete AudioRecord successfully");
    }
    else
    {
        ALOGV("Handle is invalid and does not deletel AudioRecord ");
    }
}

void AudioRecord_start(RecordHandle handle)
{
    ALOGV("Enter AudioRecord_start");
    if (handle != NULL)
    {
        static_cast<AudioRecord*>(handle)->start();
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioRecord start");
    }
}

void AudioRecord_stop(RecordHandle handle)
{
    ALOGV("Enter AudioRecord_stop");
    if (handle != NULL)
    {
        static_cast<AudioRecord*>(handle)->stop();
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioRecord stop");
    }
}

status_type AudioRecord_getposition(RecordHandle handle, int32_t *position)
{
    ALOGV("Enter AudioRecord_getposition");
    status_type result = INVALID_PARAM;
    status_t andrresult;

    if (handle != NULL && position != NULL)
    {
        andrresult = static_cast<AudioRecord*>(handle)->getPosition((uint32_t*) position);
        result = (status_type) andrresult;
        ALOGV("Call AudioRecord getPosition and result is %d, position=%d.",
                                                    andrresult, *position);
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioRecord getPosition");
    }
    return result;
}

size_t AudioRecord_read(RecordHandle handle, void *buffer, size_t size)
{
    ALOGV("Enter AudioRecord_read and size is %d.", size);
    size_t result = 0;

    if (handle != NULL && buffer != NULL && size > 0)
    {
        result = static_cast<AudioRecord*>(handle)->read(buffer, size);
        ALOGV("Call AudioRecored read and result is %d.", result);
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioRecord read");
    }
    return result;
}

status_type AudioRecord_set(RecordHandle handle, audio_source_t inputsource,
                uint32 samplerate, audio_format_t format,
                audio_channel_mask_t channel)
{
    ALOGV("Enter AudioRecord_set and audiosource is %d.", inputsource);
    status_type result = INVALID_PARAM;
    status_t andrresult;

    if (handle != NULL)
    {
        andrresult = static_cast<AudioRecord*>(handle)->set(inputsource,
			samplerate, format, channel);
        result = (status_type) andrresult;
        ALOGV("Call AudioRecord set and result is %d", andrresult);
    }
    else
    {
        ALOGV("Handle is invalid and does not call AudioRecord set");
    }
    return result;
}

uint32 AudioRecord_latency(RecordHandle handle)
{
    ALOGV("Enter AudioRecord_latency");
    uint32 result = 0;
    if (handle != NULL)
        result = static_cast<AudioRecord*>(handle)->latency();
    else
        ALOGV("Handle is invalid and does not call AudioRecord latency");

    return result;
}

AudioIOHandle AudioSystem_getOutput(audio_stream_type_t streamtype,
                                    uint32 samplerate,
                                    audio_format_t format,
                                    audio_channel_mask_t channels,
                                    audio_output_flags_t flags)
{
    ALOGV(">> AudioSystem_getOutput.");
    return AudioSystem::getOutput(streamtype, samplerate, format, channels, flags);
}

status_type AudioSystem_setParameters(AudioIOHandle ioHandle, char *keyvaluepairs)
{
    ALOGV(">> AudioSystem_setParameters, iohandle %d, keypairs %s.", ioHandle, keyvaluepairs);
    return AudioSystem::setParameters(ioHandle, String8(keyvaluepairs));
}

const char * AudioSystem_getParameters(AudioIOHandle ioHandle, char *keys)
{
    ALOGV(">> AudioSystem_getParameters, iohandle %d, keys %s", ioHandle, keys);
    String8 result = AudioSystem::getParameters(ioHandle, String8(keys));
    return strdup(result.string());
}

/* Audio System related interface */

/* Master */
status_type AudioSystem_setMasterVolume(float value)
{
    ALOGV(">> AudioSystem_setMasterVolume %f.", value);
    return AudioSystem::setMasterVolume(value);
}

status_type AudioSystem_getMasterVolume(float *value)
{
    ALOGV(">> AudioSystem_getMasterVolume.");
    return AudioSystem::getMasterVolume(value);
}

status_type AudioSystem_setMasterMute(int mute)
{
    ALOGV(">> AudioSystem_setMasterMute %d.", mute);
    return AudioSystem::setMasterMute(mute);
}

status_type AudioSystem_getMasterMute(int *mute)
{
    ALOGV(">> AudioSystem_getMasterMute.");
    return AudioSystem::getMasterMute((bool*) mute);
}

status_type AudioSystem_muteMicrophone(int state)
{
    ALOGV(">> AudioSystem_muteMicrophone %d.", state);
    return AudioSystem::muteMicrophone(state);
}

status_type AudioSystem_isMicrophoneMuted(int *state)
{
    ALOGV(">> AudioSystem_isMicrophoneMuted.");
    return AudioSystem::isMicrophoneMuted((bool*) state);
}

status_type AudioSystem_setMode(audio_mode_t mode)
{
    ALOGV(">> AudioSystem_setMode %d.", (int) mode);
    return AudioSystem::setMode(mode);
}

status_type AudioSystem_setVoiceVolume(float volume)
{
    ALOGV(">> AudioSystem_setVoiceVolume %f.", volume);
    return AudioSystem::setVoiceVolume(volume);
}

/* Stream */
status_type AudioSystem_initStreamVolume(audio_stream_type_t streamtype, int indexMin, int indexMax)
{
    ALOGV(">> AudioSystem_initStreamVolume: streamtype is %d.", streamtype);
    return AudioSystem::initStreamVolume(streamtype, indexMin, indexMax);
}

status_type AudioSystem_getStreamVolumeIndex(audio_stream_type_t streamtype,
                                             int *index, audio_devices_t device)
{
    ALOGV(">> AudioSystem_getStreamVolumeIndex: streamtype is %d.", streamtype);
    return AudioSystem::getStreamVolumeIndex(streamtype, index, device);
}

status_type AudioSystem_getStreamMute(audio_stream_type_t streamtype, int *mute)
{
    ALOGV(">> AudioSystem_getStreamMute: streamtype is %d.", streamtype);
    return AudioSystem::getStreamMute(streamtype, (bool*) mute);
}

status_type AudioSystem_setStreamVolumeIndex(audio_stream_type_t streamtype,
		                             int index, audio_devices_t device)
{
    ALOGV(">> AudioSystem_setStreamVolumeIndex:streamtype is %d.", streamtype);
    return AudioSystem::setStreamVolumeIndex(streamtype, index, device);
}

status_type AudioSystem_setStreamMute(audio_stream_type_t streamtype, int mute)
{
    ALOGV(">> AudioSystem_setStreamMute:streamtype is %d.", streamtype);
    return AudioSystem::setStreamMute(streamtype, mute);
}

status_type AudioSystem_setStreamVolume(audio_stream_type_t streamtype, float value, int output)
{
    ALOGV(">> AudioSystem_setStreamVolume %f.", value);
    return AudioSystem::setStreamVolume(streamtype, value, output);
}

status_type AudioSystem_getStreamVolume(audio_stream_type_t streamtype, float *value, int output)
{
    ALOGV(">> AudioSystem_getStreamVolume.");
    return AudioSystem::getStreamVolume(streamtype, value, output);
}

} // extern "C"


