/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "voe_file_impl.h"

#include "channel.h"
#include "critical_section_wrapper.h"
#include "file_wrapper.h"
#include "media_file.h"
#include "output_mixer.h"
#include "trace.h"
#include "transmit_mixer.h"
#include "voe_errors.h"
#include "voice_engine_impl.h"

namespace webrtc {

VoEFile* VoEFile::GetInterface(VoiceEngine* voiceEngine)
{
#ifndef WEBRTC_VOICE_ENGINE_FILE_API
    return NULL;
#else
    if (NULL == voiceEngine)
    {
        return NULL;
    }
    VoiceEngineImpl* s = reinterpret_cast<VoiceEngineImpl*>(voiceEngine);
    s->AddRef();
    return s;
#endif
}

#ifdef WEBRTC_VOICE_ENGINE_FILE_API

VoEFileImpl::VoEFileImpl(voe::SharedData* shared) : _shared(shared)
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "VoEFileImpl::VoEFileImpl() - ctor");
}

VoEFileImpl::~VoEFileImpl()
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "VoEFileImpl::~VoEFileImpl() - dtor");
}

int VoEFileImpl::StartPlayingFileLocally(
    int channel,
    const char fileNameUTF8[1024],
    bool loop, FileFormats format,
    float volumeScaling,
    int startPointMs,
    int stopPointMs)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StartPlayingFileLocally(channel=%d, fileNameUTF8[]=%s, "
                 "loop=%d, format=%d, volumeScaling=%5.3f, startPointMs=%d,"
                 " stopPointMs=%d)",
                 channel, fileNameUTF8, loop, format, volumeScaling,
                 startPointMs, stopPointMs);
    assert(1024 == FileWrapper::kMaxFileNameSize);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "StartPlayingFileLocally() failed to locate channel");
        return -1;
    }

    return channelPtr->StartPlayingFileLocally(fileNameUTF8,
                                               loop,
                                               format,
                                               startPointMs,
                                               volumeScaling,
                                               stopPointMs,
                                               NULL);
}

int VoEFileImpl::StartPlayingFileLocally(int channel,
                                         InStream* stream,
                                         FileFormats format,
                                         float volumeScaling,
                                         int startPointMs,
                                         int stopPointMs)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StartPlayingFileLocally(channel=%d, stream, format=%d, "
                 "volumeScaling=%5.3f, startPointMs=%d, stopPointMs=%d)",
                 channel, format, volumeScaling, startPointMs, stopPointMs);

    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }

    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "StartPlayingFileLocally() failed to locate channel");
        return -1;
    }

    return channelPtr->StartPlayingFileLocally(stream,
                                               format,
                                               startPointMs,
                                               volumeScaling,
                                               stopPointMs,
                                               NULL);
}

int VoEFileImpl::StopPlayingFileLocally(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StopPlayingFileLocally()");
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "StopPlayingFileLocally() failed to locate channel");
        return -1;
    }
    return channelPtr->StopPlayingFileLocally();
}

int VoEFileImpl::IsPlayingFileLocally(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "IsPlayingFileLocally(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "StopPlayingFileLocally() failed to locate channel");
        return -1;
    }
    return channelPtr->IsPlayingFileLocally();
}

int VoEFileImpl::ScaleLocalFilePlayout(int channel, float scale)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ScaleLocalFilePlayout(channel=%d, scale=%5.3f)",
                 channel, scale);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "StopPlayingFileLocally() failed to locate channel");
        return -1;
    }
    return channelPtr->ScaleLocalFilePlayout(scale);
}

int VoEFileImpl::StartPlayingFileAsMicrophone(int channel,
                                              const char fileNameUTF8[1024],
                                              bool loop,
                                              bool mixWithMicrophone,
                                              FileFormats format,
                                              float volumeScaling)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StartPlayingFileAsMicrophone(channel=%d, fileNameUTF8=%s, "
                 "loop=%d, mixWithMicrophone=%d, format=%d, "
                 "volumeScaling=%5.3f)",
                 channel, fileNameUTF8, loop, mixWithMicrophone, format,
                 volumeScaling);
    assert(1024 == FileWrapper::kMaxFileNameSize);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }

    const WebRtc_UWord32 startPointMs(0);
    const WebRtc_UWord32 stopPointMs(0);

    if (channel == -1)
    {
        int res = _shared->transmit_mixer()->StartPlayingFileAsMicrophone(
            fileNameUTF8,
            loop,
            format,
            startPointMs,
            volumeScaling,
            stopPointMs,
            NULL);
        if (res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StartPlayingFileAsMicrophone() failed to start playing file");
            return(-1);
        }
        else
        {
            _shared->transmit_mixer()->SetMixWithMicStatus(mixWithMicrophone);
            return(0);
        }
    }
    else
    {
        // Add file after demultiplexing <=> affects one channel only
        voe::ScopedChannel sc(_shared->channel_manager(), channel);
        voe::Channel* channelPtr = sc.ChannelPtr();
        if (channelPtr == NULL)
        {
            _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                "StartPlayingFileAsMicrophone() failed to locate channel");
            return -1;
        }

        int res = channelPtr->StartPlayingFileAsMicrophone(fileNameUTF8,
                                                           loop,
                                                           format,
                                                           startPointMs,
                                                           volumeScaling,
                                                           stopPointMs,
                                                           NULL);
        if (res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StartPlayingFileAsMicrophone() failed to start playing file");
            return -1;
        }
        else
        {
            channelPtr->SetMixWithMicStatus(mixWithMicrophone);
            return 0;
        }
    }
}

int VoEFileImpl::StartPlayingFileAsMicrophone(int channel,
                                              InStream* stream,
                                              bool mixWithMicrophone,
                                              FileFormats format,
                                              float volumeScaling)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StartPlayingFileAsMicrophone(channel=%d, stream,"
                 " mixWithMicrophone=%d, format=%d, volumeScaling=%5.3f)",
                 channel, mixWithMicrophone, format, volumeScaling);

    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }

    const WebRtc_UWord32 startPointMs(0);
    const WebRtc_UWord32 stopPointMs(0);

    if (channel == -1)
    {
        int res = _shared->transmit_mixer()->StartPlayingFileAsMicrophone(
            stream,
            format,
            startPointMs,
            volumeScaling,
            stopPointMs,
            NULL);
        if (res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StartPlayingFileAsMicrophone() failed to start "
                "playing stream");
            return(-1);
        }
        else
        {
            _shared->transmit_mixer()->SetMixWithMicStatus(mixWithMicrophone);
            return(0);
        }
    }
    else
    {
        // Add file after demultiplexing <=> affects one channel only
        voe::ScopedChannel sc(_shared->channel_manager(), channel);
        voe::Channel* channelPtr = sc.ChannelPtr();
        if (channelPtr == NULL)
        {
            _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                "StartPlayingFileAsMicrophone() failed to locate channel");
            return -1;
        }

        int res = channelPtr->StartPlayingFileAsMicrophone(
            stream, format, startPointMs, volumeScaling, stopPointMs, NULL);
        if (res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StartPlayingFileAsMicrophone() failed to start "
                "playing stream");
            return -1;
        }
        else
        {
            channelPtr->SetMixWithMicStatus(mixWithMicrophone);
            return 0;
        }
    }
}

int VoEFileImpl::StopPlayingFileAsMicrophone(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StopPlayingFileAsMicrophone(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (channel == -1)
    {
        // Stop adding file before demultiplexing <=> affects all channels
        return _shared->transmit_mixer()->StopPlayingFileAsMicrophone();
    }
    else
    {
        // Stop adding file after demultiplexing <=> affects one channel only
        voe::ScopedChannel sc(_shared->channel_manager(), channel);
        voe::Channel* channelPtr = sc.ChannelPtr();
        if (channelPtr == NULL)
        {
            _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                "StopPlayingFileAsMicrophone() failed to locate channel");
            return -1;
        }
        return channelPtr->StopPlayingFileAsMicrophone();
    }
}

int VoEFileImpl::IsPlayingFileAsMicrophone(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "IsPlayingFileAsMicrophone(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (channel == -1)
    {
        return _shared->transmit_mixer()->IsPlayingFileAsMicrophone();
    }
    else
    {
        // Stop adding file after demultiplexing <=> affects one channel only
        voe::ScopedChannel sc(_shared->channel_manager(), channel);
        voe::Channel* channelPtr = sc.ChannelPtr();
        if (channelPtr == NULL)
        {
            _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                "IsPlayingFileAsMicrophone() failed to locate channel");
            return -1;
        }
        return channelPtr->IsPlayingFileAsMicrophone();
    }
}

int VoEFileImpl::ScaleFileAsMicrophonePlayout(int channel, float scale)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ScaleFileAsMicrophonePlayout(channel=%d, scale=%5.3f)",
                 channel, scale);

    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (channel == -1)
    {
        return _shared->transmit_mixer()->ScaleFileAsMicrophonePlayout(scale);
    }
    else
    {
        // Stop adding file after demultiplexing <=> affects one channel only
        voe::ScopedChannel sc(_shared->channel_manager(), channel);
        voe::Channel* channelPtr = sc.ChannelPtr();
        if (channelPtr == NULL)
        {
            _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                "IsPlayingFileAsMicrophone() failed to locate channel");
            return -1;
        }
        return channelPtr->ScaleFileAsMicrophonePlayout(scale);
    }
}

int VoEFileImpl::StartRecordingPlayout(
    int channel, const char* fileNameUTF8, CodecInst* compression,
    int maxSizeBytes)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StartRecordingPlayout(channel=%d, fileNameUTF8=%s, "
                 "compression, maxSizeBytes=%d)",
                 channel, fileNameUTF8, maxSizeBytes);
    assert(1024 == FileWrapper::kMaxFileNameSize);

    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (channel == -1)
    {
        return _shared->output_mixer()->StartRecordingPlayout
          (fileNameUTF8, compression);
    }
    else
    {
        // Add file after demultiplexing <=> affects one channel only
        voe::ScopedChannel sc(_shared->channel_manager(), channel);
        voe::Channel* channelPtr = sc.ChannelPtr();
        if (channelPtr == NULL)
        {
            _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                "StartRecordingPlayout() failed to locate channel");
            return -1;
        }
        return channelPtr->StartRecordingPlayout(fileNameUTF8, compression);
    }
}

int VoEFileImpl::StartRecordingPlayout(
    int channel, OutStream* stream, CodecInst* compression)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StartRecordingPlayout(channel=%d, stream, compression)",
                 channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (channel == -1)
    {
        return _shared->output_mixer()->
            StartRecordingPlayout(stream, compression);
    }
    else
    {
        voe::ScopedChannel sc(_shared->channel_manager(), channel);
        voe::Channel* channelPtr = sc.ChannelPtr();
        if (channelPtr == NULL)
        {
            _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                "StartRecordingPlayout() failed to locate channel");
            return -1;
        }
        return channelPtr->StartRecordingPlayout(stream, compression);
    }
}

int VoEFileImpl::StopRecordingPlayout(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StopRecordingPlayout(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (channel == -1)
    {
        return _shared->output_mixer()->StopRecordingPlayout();
    }
    else
    {
        voe::ScopedChannel sc(_shared->channel_manager(), channel);
        voe::Channel* channelPtr = sc.ChannelPtr();
        if (channelPtr == NULL)
        {
            _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
                "StopRecordingPlayout() failed to locate channel");
            return -1;
        }
        return channelPtr->StopRecordingPlayout();
    }
}

int VoEFileImpl::StartRecordingMicrophone(
    const char* fileNameUTF8, CodecInst* compression, int maxSizeBytes)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StartRecordingMicrophone(fileNameUTF8=%s, compression, "
                 "maxSizeBytes=%d)", fileNameUTF8, maxSizeBytes);
    assert(1024 == FileWrapper::kMaxFileNameSize);

    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (_shared->transmit_mixer()->StartRecordingMicrophone(fileNameUTF8,
                                                          compression))
    {
        WEBRTC_TRACE(kTraceError, kTraceVoice,
            VoEId(_shared->instance_id(), -1),
            "StartRecordingMicrophone() failed to start recording");
        return -1;
    }
    if (_shared->audio_device()->Recording())
    {
        return 0;
    }
    if (!_shared->ext_recording())
    {
        if (_shared->audio_device()->InitRecording() != 0)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StartRecordingMicrophone() failed to initialize recording");
            return -1;
        }
        if (_shared->audio_device()->StartRecording() != 0)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StartRecordingMicrophone() failed to start recording");
            return -1;
        }
    }
    return 0;
}

int VoEFileImpl::StartRecordingMicrophone(
    OutStream* stream, CodecInst* compression)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StartRecordingMicrophone(stream, compression)");

    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (_shared->transmit_mixer()->StartRecordingMicrophone(stream,
                                                          compression) == -1)
    {
        WEBRTC_TRACE(kTraceError, kTraceVoice,
            VoEId(_shared->instance_id(), -1),
            "StartRecordingMicrophone() failed to start recording");
        return -1;
    }
    if (_shared->audio_device()->Recording())
    {
        return 0;
    }
    if (!_shared->ext_recording())
    {
        if (_shared->audio_device()->InitRecording() != 0)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StartRecordingMicrophone() failed to initialize recording");
            return -1;
        }
        if (_shared->audio_device()->StartRecording() != 0)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StartRecordingMicrophone() failed to start recording");
            return -1;
        }
    }
    return 0;
}

int VoEFileImpl::StopRecordingMicrophone()
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "StopRecordingMicrophone()");
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }

    int err = 0;

    // TODO(xians): consider removing Start/StopRecording() in
    // Start/StopRecordingMicrophone() if no channel is recording.
    if (_shared->NumOfSendingChannels() == 0 &&
        _shared->audio_device()->Recording())
    {
        // Stop audio-device recording if no channel is recording
        if (_shared->audio_device()->StopRecording() != 0)
        {
            _shared->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,
                "StopRecordingMicrophone() failed to stop recording");
            err = -1;
        }
    }

    if (_shared->transmit_mixer()->StopRecordingMicrophone() != 0)
    {
        WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "StopRecordingMicrophone() failed to stop recording to mixer");
        err = -1;
    }

    return err;
}

// TODO(andrew): a cursory inspection suggests there's a large amount of
// overlap in these convert functions which could be refactored to a helper.
int VoEFileImpl::ConvertPCMToWAV(const char* fileNameInUTF8,
                                 const char* fileNameOutUTF8)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ConvertPCMToWAV(fileNameInUTF8=%s, fileNameOutUTF8=%s)",
                 fileNameInUTF8, fileNameOutUTF8);

    // Create file player object
    FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
        -1,
        kFileFormatPcm16kHzFile));

    int res=playerObj.StartPlayingFile(fileNameInUTF8,false,0,1.0,0,0, NULL);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertPCMToWAV failed to create player object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        return -1;
    }

    // Create file recorder object
    FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
        -1, kFileFormatWavFile));

    CodecInst codecInst;
    strncpy(codecInst.plname,"L16",32);
            codecInst.channels = 1;
            codecInst.rate     = 256000;
            codecInst.plfreq   = 16000;
            codecInst.pltype   = 94;
            codecInst.pacsize  = 160;

    res = recObj.StartRecordingAudioFile(fileNameOutUTF8,codecInst,0);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertPCMToWAV failed to create recorder object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        recObj.StopRecording();
        FileRecorder::DestroyFileRecorder(&recObj);
        return -1;
    }

    // Run throught the file
    AudioFrame audioFrame;
    WebRtc_Word16 decodedData[160];
    int decLength=0;
    const WebRtc_UWord32 frequency = 16000;

    while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
    {
        if(decLength!=frequency/100)
        {
            // This is an OK way to end
            break;
        }

        res=audioFrame.UpdateFrame(-1, 0, decodedData,
                                  (WebRtc_UWord16)decLength,
                                   frequency, AudioFrame::kNormalSpeech,
                                   AudioFrame::kVadActive);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertPCMToWAV failed during conversion (audio frame)");
            break;
        }

        res=recObj.RecordAudioToFile(audioFrame);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertPCMToWAV failed during conversion (write frame)");
        }
    }

    playerObj.StopPlayingFile();
    recObj.StopRecording();
    FilePlayer::DestroyFilePlayer(&playerObj);
    FileRecorder::DestroyFileRecorder(&recObj);

    return res;
}

int VoEFileImpl::ConvertPCMToWAV(InStream* streamIn, OutStream* streamOut)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ConvertPCMToWAV(streamIn, streamOut)");

    if ((streamIn == NULL) || (streamOut == NULL))
    {
        WEBRTC_TRACE(kTraceError, kTraceVoice,
            VoEId(_shared->instance_id(), -1), "invalid stream handles");
        return (-1);
    }

    // Create file player object
    FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(-1,
        kFileFormatPcm16kHzFile));
    int res = playerObj.StartPlayingFile(*streamIn,0,1.0,0,0,NULL);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertPCMToWAV failed to create player object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        return -1;
    }

    // Create file recorder object
    FileRecorder& recObj(*FileRecorder::CreateFileRecorder(-1,
        kFileFormatWavFile));
    CodecInst codecInst;
    strncpy(codecInst.plname, "L16", 32);
            codecInst.channels = 1;
            codecInst.rate     = 256000;
            codecInst.plfreq   = 16000;
            codecInst.pltype   = 94;
            codecInst.pacsize  = 160;
    res = recObj.StartRecordingAudioFile(*streamOut,codecInst,0);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertPCMToWAV failed to create recorder object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        recObj.StopRecording();
        FileRecorder::DestroyFileRecorder(&recObj);
        return -1;
    }

    // Run throught the file
    AudioFrame audioFrame;
    WebRtc_Word16 decodedData[160];
    int decLength=0;
    const WebRtc_UWord32 frequency = 16000;

    while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
    {
        if(decLength!=frequency/100)
        {
            // This is an OK way to end
            break;
        }

        res=audioFrame.UpdateFrame(-1, 0, decodedData,
                                  (WebRtc_UWord16)decLength, frequency,
                                   AudioFrame::kNormalSpeech,
                                   AudioFrame::kVadActive);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertPCMToWAV failed during conversion "
                "(create audio frame)");
            break;
        }

        res=recObj.RecordAudioToFile(audioFrame);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertPCMToWAV failed during conversion (write frame)");
        }
    }

    playerObj.StopPlayingFile();
    recObj.StopRecording();
    FilePlayer::DestroyFilePlayer(&playerObj);
    FileRecorder::DestroyFileRecorder(&recObj);

    return res;
}

int VoEFileImpl::ConvertWAVToPCM(const char* fileNameInUTF8,
                                 const char* fileNameOutUTF8)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ConvertWAVToPCM(fileNameInUTF8=%s, fileNameOutUTF8=%s)",
                 fileNameInUTF8, fileNameOutUTF8);

    // Create file player object
    FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(-1,
                                                        kFileFormatWavFile));
    int res = playerObj.StartPlayingFile(fileNameInUTF8,false,0,1.0,0,0,NULL);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertWAVToPCM failed to create player object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        return -1;
    }

    // Create file recorder object
    FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
        -1, kFileFormatPcm16kHzFile));

    CodecInst codecInst;
    strncpy(codecInst.plname,"L16",32);
            codecInst.channels = 1;
            codecInst.rate     = 256000;
            codecInst.plfreq   = 16000;
            codecInst.pltype   = 94;
            codecInst.pacsize  = 160;

    res = recObj.StartRecordingAudioFile(fileNameOutUTF8,codecInst,0);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertWAVToPCM failed to create recorder object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        recObj.StopRecording();
        FileRecorder::DestroyFileRecorder(&recObj);
        return -1;
    }

    // Run throught the file
    AudioFrame audioFrame;
    WebRtc_Word16 decodedData[160];
    int decLength=0;
    const WebRtc_UWord32 frequency = 16000;

    while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
    {
        if(decLength!=frequency/100)
        {
            // This is an OK way to end
            break;
        }

        res=audioFrame.UpdateFrame(-1, 0, decodedData,
                                   (WebRtc_UWord16)decLength,
                                   frequency, AudioFrame::kNormalSpeech,
                                   AudioFrame::kVadActive);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertWAVToPCM failed during conversion (audio frame)");
            break;
        }

        res=recObj.RecordAudioToFile(audioFrame);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertWAVToPCM failed during conversion (write frame)");
        }
    }

    playerObj.StopPlayingFile();
    recObj.StopRecording();
    FilePlayer::DestroyFilePlayer(&playerObj);
    FileRecorder::DestroyFileRecorder(&recObj);

    return res;
}

int VoEFileImpl::ConvertWAVToPCM(InStream* streamIn, OutStream* streamOut)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ConvertWAVToPCM(streamIn, streamOut)");

    if ((streamIn == NULL) || (streamOut == NULL))
    {
        WEBRTC_TRACE(kTraceError, kTraceVoice,
          VoEId(_shared->instance_id(), -1), "invalid stream handles");
        return (-1);
    }

    // Create file player object
    FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(-1,
                                                        kFileFormatWavFile));
    int res = playerObj.StartPlayingFile(*streamIn,0,1.0,0,0,NULL);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertWAVToPCM failed to create player object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        return -1;
    }

    // Create file recorder object
    FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
        -1, kFileFormatPcm16kHzFile));

    CodecInst codecInst;
    strncpy(codecInst.plname,"L16",32);
            codecInst.channels = 1;
            codecInst.rate     = 256000;
            codecInst.plfreq   = 16000;
            codecInst.pltype   = 94;
            codecInst.pacsize  = 160;

    res = recObj.StartRecordingAudioFile(*streamOut,codecInst,0);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertWAVToPCM failed to create recorder object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        recObj.StopRecording();
        FileRecorder::DestroyFileRecorder(&recObj);
        return -1;
    }

    // Run throught the file
    AudioFrame audioFrame;
    WebRtc_Word16 decodedData[160];
    int decLength=0;
    const WebRtc_UWord32 frequency = 16000;

    while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
    {
        if(decLength!=frequency/100)
        {
            // This is an OK way to end
            break;
        }

        res=audioFrame.UpdateFrame(-1, 0, decodedData,
                                  (WebRtc_UWord16)decLength, frequency,
                                   AudioFrame::kNormalSpeech,
                                   AudioFrame::kVadActive);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertWAVToPCM failed during conversion (audio frame)");
            break;
        }

        res=recObj.RecordAudioToFile(audioFrame);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertWAVToPCM failed during conversion (write frame)");
        }
    }

    playerObj.StopPlayingFile();
    recObj.StopRecording();
    FilePlayer::DestroyFilePlayer(&playerObj);
    FileRecorder::DestroyFileRecorder(&recObj);

    return res;
}

int VoEFileImpl::ConvertPCMToCompressed(const char* fileNameInUTF8,
                                        const char* fileNameOutUTF8,
                                        CodecInst* compression)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ConvertPCMToCompressed(fileNameInUTF8=%s, fileNameOutUTF8=%s"
                 ",  compression)", fileNameInUTF8, fileNameOutUTF8);
    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "  compression: plname=%s, plfreq=%d, pacsize=%d",
                 compression->plname, compression->plfreq,
                 compression->pacsize);

    // Create file player object
    FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
        -1,
        kFileFormatPcm16kHzFile));
    int res = playerObj.StartPlayingFile(fileNameInUTF8,false,0,1.0,0,0, NULL);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertPCMToCompressed failed to create player object");
        // Clean up and shutdown the file player
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        return -1;
    }

    // Create file recorder object
    FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
        -1,
        kFileFormatCompressedFile));
    res = recObj.StartRecordingAudioFile(fileNameOutUTF8, *compression,0);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertPCMToCompressed failed to create recorder object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        recObj.StopRecording();
        FileRecorder::DestroyFileRecorder(&recObj);
        return -1;
    }

    // Run throught the file
    AudioFrame audioFrame;
    WebRtc_Word16 decodedData[160];
    int decLength=0;
    const WebRtc_UWord32 frequency = 16000;

    while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
    {
        if(decLength!=frequency/100)
        {
            // This is an OK way to end
            break;
        }
        res=audioFrame.UpdateFrame(-1, 0, decodedData,
                                  (WebRtc_UWord16)decLength,
                                  frequency, AudioFrame::kNormalSpeech,
                                  AudioFrame::kVadActive);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertPCMToCompressed failed during conversion "
                "(audio frame)");
            break;
        }

        res=recObj.RecordAudioToFile(audioFrame);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertPCMToCompressed failed during conversion "
                "(write frame)");
        }
    }

    playerObj.StopPlayingFile();
    recObj.StopRecording();
    FilePlayer::DestroyFilePlayer(&playerObj);
    FileRecorder::DestroyFileRecorder(&recObj);

    return res;
}

int VoEFileImpl::ConvertPCMToCompressed(InStream* streamIn,
                                        OutStream* streamOut,
                                        CodecInst* compression)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ConvertPCMToCompressed(streamIn, streamOut, compression)");

    if ((streamIn == NULL) || (streamOut == NULL))
    {
        WEBRTC_TRACE(kTraceError, kTraceVoice,
            VoEId(_shared->instance_id(), -1), "invalid stream handles");
        return (-1);
    }

    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "  compression: plname=%s, plfreq=%d, pacsize=%d",
                 compression->plname, compression->plfreq,
                 compression->pacsize);

    // Create file player object
    FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
        -1, kFileFormatPcm16kHzFile));

    int res = playerObj.StartPlayingFile(*streamIn,0,1.0,0,0,NULL);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertPCMToCompressed failed to create player object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        return -1;
    }

    // Create file recorder object
    FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
        -1, kFileFormatCompressedFile));
    res = recObj.StartRecordingAudioFile(*streamOut,*compression,0);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertPCMToCompressed failed to create recorder object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        recObj.StopRecording();
        FileRecorder::DestroyFileRecorder(&recObj);
        return -1;
    }

    // Run throught the file
    AudioFrame audioFrame;
    WebRtc_Word16 decodedData[160];
    int decLength=0;
    const WebRtc_UWord32 frequency = 16000;

    while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
    {
        if(decLength!=frequency/100)
        {
            // This is an OK way to end
            break;
        }
        res=audioFrame.UpdateFrame(-1, 0, decodedData,
                                  (WebRtc_UWord16)decLength,
                                   frequency, AudioFrame::kNormalSpeech,
                                   AudioFrame::kVadActive);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertPCMToCompressed failed during conversion "
                "(audio frame)");
            break;
        }

        res=recObj.RecordAudioToFile(audioFrame);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertPCMToCompressed failed during conversion "
                "(write frame)");
        }
    }

    playerObj.StopPlayingFile();
    recObj.StopRecording();
    FilePlayer::DestroyFilePlayer(&playerObj);
    FileRecorder::DestroyFileRecorder(&recObj);

    return res;
}

int VoEFileImpl::ConvertCompressedToPCM(const char* fileNameInUTF8,
                                        const char* fileNameOutUTF8)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ConvertCompressedToPCM(fileNameInUTF8=%s,"
                 " fileNameOutUTF8=%s)",
                 fileNameInUTF8, fileNameOutUTF8);

    // Create file player object
    FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
        -1, kFileFormatCompressedFile));

    int res = playerObj.StartPlayingFile(fileNameInUTF8,false,0,1.0,0,0,NULL);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertCompressedToPCM failed to create player object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        return -1;
    }

    // Create file recorder object
    FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
        -1, kFileFormatPcm16kHzFile));

    CodecInst codecInst;
    strncpy(codecInst.plname,"L16",32);
            codecInst.channels = 1;
            codecInst.rate     = 256000;
            codecInst.plfreq   = 16000;
            codecInst.pltype   = 94;
            codecInst.pacsize  = 160;

    res = recObj.StartRecordingAudioFile(fileNameOutUTF8,codecInst,0);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertCompressedToPCM failed to create recorder object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        recObj.StopRecording();
        FileRecorder::DestroyFileRecorder(&recObj);
        return -1;
    }

    // Run throught the file
    AudioFrame audioFrame;
    WebRtc_Word16 decodedData[160];
    int decLength=0;
    const WebRtc_UWord32 frequency = 16000;

    while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
    {
        if(decLength!=frequency/100)
        {
            // This is an OK way to end
            break;
        }
        res=audioFrame.UpdateFrame(-1, 0, decodedData,
                                  (WebRtc_UWord16)decLength,
                                   frequency,
                                   AudioFrame::kNormalSpeech,
                                   AudioFrame::kVadActive);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertCompressedToPCM failed during conversion "
                "(create audio frame)");
            break;
        }

        res=recObj.RecordAudioToFile(audioFrame);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertCompressedToPCM failed during conversion "
                "(write frame)");
        }
    }

    playerObj.StopPlayingFile();
    recObj.StopRecording();
    FilePlayer::DestroyFilePlayer(&playerObj);
    FileRecorder::DestroyFileRecorder(&recObj);

    return res;
}

int VoEFileImpl::ConvertCompressedToPCM(InStream* streamIn,
                                        OutStream* streamOut)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ConvertCompressedToPCM(file, file);");

    if ((streamIn == NULL) || (streamOut == NULL))
    {
        WEBRTC_TRACE(kTraceError, kTraceVoice,
            VoEId(_shared->instance_id(), -1), "invalid stream handles");
        return (-1);
    }

    // Create file player object
    FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
        -1, kFileFormatCompressedFile));
    int res;

    res = playerObj.StartPlayingFile(*streamIn,0,1.0,0,0,NULL);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertCompressedToPCM failed to create player object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        return -1;
    }

    // Create file recorder object
    FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
        -1, kFileFormatPcm16kHzFile));

    CodecInst codecInst;
    strncpy(codecInst.plname,"L16",32);
            codecInst.channels = 1;
            codecInst.rate     = 256000;
            codecInst.plfreq   = 16000;
            codecInst.pltype   = 94;
            codecInst.pacsize  = 160;

    res = recObj.StartRecordingAudioFile(*streamOut,codecInst,0);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "ConvertCompressedToPCM failed to create recorder object");
        playerObj.StopPlayingFile();
        FilePlayer::DestroyFilePlayer(&playerObj);
        recObj.StopRecording();
        FileRecorder::DestroyFileRecorder(&recObj);
        return -1;
    }

    // Run throught the file
    AudioFrame audioFrame;
    WebRtc_Word16 decodedData[160];
    int decLength=0;
    const WebRtc_UWord32 frequency = 16000;

    while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
    {
        if(decLength!=frequency/100)
        {
            // This is an OK way to end
            break;
        }
        res=audioFrame.UpdateFrame(-1, 0, decodedData,
                                  (WebRtc_UWord16)decLength,
                                   frequency,
                                   AudioFrame::kNormalSpeech,
                                   AudioFrame::kVadActive);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertCompressedToPCM failed during conversion "
                "(audio frame)");
            break;
        }

        res=recObj.RecordAudioToFile(audioFrame);
        if(res)
        {
            WEBRTC_TRACE(kTraceError, kTraceVoice,
                VoEId(_shared->instance_id(), -1),
                "ConvertCompressedToPCM failed during conversion "
                "(write frame)");
        }
    }

    playerObj.StopPlayingFile();
    recObj.StopRecording();
    FilePlayer::DestroyFilePlayer(&playerObj);
    FileRecorder::DestroyFileRecorder(&recObj);

    return res;
}


int VoEFileImpl::GetFileDuration(const char* fileNameUTF8,
                                 int& durationMs,
                                 FileFormats format)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetFileDuration(fileNameUTF8=%s, format=%d)",
                 fileNameUTF8, format);

    // Create a dummy file module for this
    MediaFile * fileModule=MediaFile::CreateMediaFile(-1);

    // Temp container of the right format
    WebRtc_UWord32 duration;
    int res=fileModule->FileDurationMs(fileNameUTF8,duration,format);
    if (res)
    {
        _shared->SetLastError(VE_BAD_FILE, kTraceError,
            "GetFileDuration() failed measure file duration");
        return -1;
    }
    durationMs = duration;
    MediaFile::DestroyMediaFile(fileModule);
    fileModule = NULL;

    return(res);
}

int VoEFileImpl::GetPlaybackPosition(int channel, int& positionMs)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPlaybackPosition(channel=%d)", channel);

    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPlaybackPosition() failed to locate channel");
        return -1;
    }
    return channelPtr->GetLocalPlayoutPosition(positionMs);
}

#endif  // #ifdef WEBRTC_VOICE_ENGINE_FILE_API

}  // namespace webrtc
