/*
 * Copyright (C) 2016 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.
 *
 */

// cribbed from samples/native-audio

#define CHATTY ALOGD
#define LOG_TAG "audioplay"

#include <binder/IServiceManager.h>

#include "audioplay.h"

#include <string.h>

#include <utils/Log.h>
#include <utils/threads.h>

// for native audio
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>

#include "BootAnimationUtil.h"

namespace audioplay {
namespace {

using namespace android;

// engine interfaces
static SLObjectItf engineObject = nullptr;
static SLEngineItf engineEngine;

// output mix interfaces
static SLObjectItf outputMixObject = nullptr;

// buffer queue player interfaces
static SLObjectItf bqPlayerObject = nullptr;
static SLPlayItf bqPlayerPlay;
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
static SLMuteSoloItf bqPlayerMuteSolo;
static SLVolumeItf bqPlayerVolume;

// pointer and size of the next player buffer to enqueue, and number of remaining buffers
static const uint8_t* nextBuffer;
static unsigned nextSize;

static const uint32_t ID_RIFF = 0x46464952;
static const uint32_t ID_WAVE = 0x45564157;
static const uint32_t ID_FMT  = 0x20746d66;
static const uint32_t ID_DATA = 0x61746164;

struct RiffWaveHeader {
    uint32_t riff_id;
    uint32_t riff_sz;
    uint32_t wave_id;
};

struct ChunkHeader {
    uint32_t id;
    uint32_t sz;
};

struct ChunkFormat {
    uint16_t audio_format;
    uint16_t num_channels;
    uint32_t sample_rate;
    uint32_t byte_rate;
    uint16_t block_align;
    uint16_t bits_per_sample;
};

// this callback handler is called every time a buffer finishes playing
void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
    (void)bq;
    (void)context;
    audioplay::setPlaying(false);
}

bool hasPlayer() {
    return (engineObject != nullptr && bqPlayerObject != nullptr);
}

// create the engine and output mix objects
bool createEngine() {
    SLresult result;

    // create engine
    result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("slCreateEngine failed with result %d", result);
        return false;
    }
    (void)result;

    // realize the engine
    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl engine Realize failed with result %d", result);
        return false;
    }
    (void)result;

    // get the engine interface, which is needed in order to create other objects
    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl engine GetInterface failed with result %d", result);
        return false;
    }
    (void)result;

    // create output mix
    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl engine CreateOutputMix failed with result %d", result);
        return false;
    }
    (void)result;

    // realize the output mix
    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl outputMix Realize failed with result %d", result);
        return false;
    }
    (void)result;

    return true;
}

// create buffer queue audio player
bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
    SLresult result;

    // configure audio source
    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1};

    // Determine channelMask from num_channels
    SLuint32 channelMask;
    switch (chunkFormat->num_channels) {
        case 1:
            channelMask = SL_SPEAKER_FRONT_CENTER;
            break;
        case 2:
            channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
            break;
        default:
            // Default of 0 will derive mask from num_channels and log a warning.
            channelMask = 0;
    }

    SLDataFormat_PCM format_pcm = {
        SL_DATAFORMAT_PCM,
        chunkFormat->num_channels,
        chunkFormat->sample_rate * 1000,  // convert to milliHz
        chunkFormat->bits_per_sample,
        16,
        channelMask,
        SL_BYTEORDER_LITTLEENDIAN
    };
    SLDataSource audioSrc = {&loc_bufq, &format_pcm};

    // configure audio sink
    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
    SLDataSink audioSnk = {&loc_outmix, nullptr};

    // create audio player
    const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME, SL_IID_ANDROIDCONFIGURATION};
    const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
            3, ids, req);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl CreateAudioPlayer failed with result %d", result);
        return false;
    }
    (void)result;

    // Use the System stream for boot sound playback.
    SLAndroidConfigurationItf playerConfig;
    result = (*bqPlayerObject)->GetInterface(bqPlayerObject,
        SL_IID_ANDROIDCONFIGURATION, &playerConfig);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("config GetInterface failed with result %d", result);
        return false;
    }
    SLint32 streamType = SL_ANDROID_STREAM_SYSTEM;
    result = (*playerConfig)->SetConfiguration(playerConfig,
        SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("SetConfiguration failed with result %d", result);
        return false;
    }
    // use normal performance mode as low latency is not needed. This is not mandatory so
    // do not bail if we fail
    SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE;
    result = (*playerConfig)->SetConfiguration(
           playerConfig, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(SLuint32));
    ALOGW_IF(result != SL_RESULT_SUCCESS,
            "could not set performance mode on player, error %d", result);
    (void)result;

    // realize the player
    result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl player Realize failed with result %d", result);
        return false;
    }
    (void)result;

    // get the play interface
    result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl player GetInterface failed with result %d", result);
        return false;
    }
    (void)result;

    // get the buffer queue interface
    result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
            &bqPlayerBufferQueue);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl playberBufferQueue GetInterface failed with result %d", result);
        return false;
    }
    (void)result;

    // register callback on the buffer queue
    result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result);
        return false;
    }
    (void)result;

    // get the volume interface
    result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
    if (result != SL_RESULT_SUCCESS) {
        ALOGE("sl volume GetInterface failed with result %d", result);
        return false;
    }
    (void)result;

    // set the player's state to playing
    audioplay::setPlaying(true);
    CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue);
    return true;
}

bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat,
                  const uint8_t** oSoundBuf, unsigned* oSoundBufSize) {
    *oSoundBuf = clipBuf;
    *oSoundBufSize = clipBufSize;
    *oChunkFormat = nullptr;
    const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf;
    if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
        (wavHeader->wave_id != ID_WAVE)) {
        ALOGE("Error: audio file is not a riff/wave file\n");
        return false;
    }
    *oSoundBuf += sizeof(*wavHeader);
    *oSoundBufSize -= sizeof(*wavHeader);

    while (true) {
        const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf;
        if (*oSoundBufSize < sizeof(*chunkHeader)) {
            ALOGE("EOF reading chunk headers");
            return false;
        }

        *oSoundBuf += sizeof(*chunkHeader);
        *oSoundBufSize -= sizeof(*chunkHeader);

        bool endLoop = false;
        switch (chunkHeader->id) {
            case ID_FMT:
                *oChunkFormat = (const ChunkFormat*)*oSoundBuf;
                *oSoundBuf += chunkHeader->sz;
                *oSoundBufSize -= chunkHeader->sz;
                break;
            case ID_DATA:
                /* Stop looking for chunks */
                *oSoundBufSize = chunkHeader->sz;
                endLoop = true;
                break;
            default:
                /* Unknown chunk, skip bytes */
                *oSoundBuf += chunkHeader->sz;
                *oSoundBufSize -= chunkHeader->sz;
        }
        if (endLoop) {
            break;
        }
    }

    if (*oChunkFormat == nullptr) {
        ALOGE("format not found in WAV file");
        return false;
    }
    return true;
}

class InitAudioThread : public Thread {
public:
    InitAudioThread(uint8_t* exampleAudioData, int exampleAudioLength)
        : Thread(false),
          mExampleAudioData(exampleAudioData),
          mExampleAudioLength(exampleAudioLength) {}

private:
    virtual bool threadLoop() {
        if (defaultServiceManager()->checkService(String16("audio")) == nullptr) {
            ALOGW("Audio service is not ready yet, ignore creating playback engine");
            return false;
        }
        audioplay::create(mExampleAudioData, mExampleAudioLength);
        // Exit immediately
        return false;
    }

    uint8_t* mExampleAudioData;
    int mExampleAudioLength;
};

// Typedef to aid readability.
typedef android::BootAnimation::Animation Animation;

class AudioAnimationCallbacks : public android::BootAnimation::Callbacks {
public:
    void init(const Vector<Animation::Part>& parts) override {
        const Animation::Part* partWithAudio = nullptr;

        if (!playSoundsAllowed()) {
            return;
        }

        for (const Animation::Part& part : parts) {
            if (part.audioData != nullptr) {
                partWithAudio = &part;
                break;
            }
        }

        if (partWithAudio == nullptr) {
            return;
        }

        ALOGD("found audio.wav, creating playback engine");
        // The audioData is used to initialize the audio system. Different data
        // can be played later for other parts BUT the assumption is that they
        // will all be the same format and only the format of this audioData
        // will work correctly.
        initAudioThread = new InitAudioThread(partWithAudio->audioData,
                partWithAudio->audioLength);
        initAudioThread->run("BootAnimation::InitAudioThread", PRIORITY_NORMAL);
    };

    void playPart(int partNumber, const Animation::Part& part, int playNumber) override {
        // only play audio file the first time we animate the part
        if (playNumber == 0 && part.audioData && playSoundsAllowed()) {
            ALOGD("playing clip for part%d, size=%d",
                  partNumber, part.audioLength);
            // Block until the audio engine is finished initializing.
            if (initAudioThread != nullptr) {
                initAudioThread->join();
            }
            audioplay::playClip(part.audioData, part.audioLength);
        }
    };

    void shutdown() override {
        // we've finally played everything we're going to play
        audioplay::setPlaying(false);
        audioplay::destroy();
    };

private:
    sp<InitAudioThread> initAudioThread = nullptr;
};

} // namespace

bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) {
    if (!createEngine()) {
        return false;
    }

    // Parse the example clip.
    const ChunkFormat* chunkFormat;
    const uint8_t* soundBuf;
    unsigned soundBufSize;
    if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) {
        return false;
    }

    // Initialize the BufferQueue based on this clip's format.
    if (!createBufferQueueAudioPlayer(chunkFormat)) {
        return false;
    }
    return true;
}

bool playClip(const uint8_t* buf, int size) {
    if (!hasPlayer()) {
        ALOGE("cannot play clip %p without a player", buf);
        return false;
    }

    // Parse the WAV header
    const ChunkFormat* chunkFormat;
    if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
        return false;
    }

    CHATTY("playClip on player %p: buf=%p size=%d nextSize %d",
           bqPlayerBufferQueue, buf, size, nextSize);

    if (nextSize > 0) {
        // here we only enqueue one buffer because it is a long clip,
        // but for streaming playback we would typically enqueue at least 2 buffers to start
        SLresult result;
        result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
        if (SL_RESULT_SUCCESS != result) {
            return false;
        }
        audioplay::setPlaying(true);
    }

    return true;
}

// set the playing state for the buffer queue audio player
void setPlaying(bool isPlaying) {
    if (!hasPlayer()) return;

    if (nullptr != bqPlayerPlay) {
        // set the player's state
        (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
            isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
    }

}

void destroy() {
    // destroy buffer queue audio player object, and invalidate all associated interfaces
    if (bqPlayerObject != nullptr) {
        CHATTY("destroying audio player");
        (*bqPlayerObject)->Destroy(bqPlayerObject);
        bqPlayerObject = nullptr;
        bqPlayerPlay = nullptr;
        bqPlayerBufferQueue = nullptr;
        bqPlayerMuteSolo = nullptr;
        bqPlayerVolume = nullptr;
    }

    // destroy output mix object, and invalidate all associated interfaces
    if (outputMixObject != nullptr) {
        (*outputMixObject)->Destroy(outputMixObject);
        outputMixObject = nullptr;
    }

    // destroy engine object, and invalidate all associated interfaces
    if (engineObject != nullptr) {
        CHATTY("destroying audio engine");
        (*engineObject)->Destroy(engineObject);
        engineObject = nullptr;
        engineEngine = nullptr;
    }
}

sp<BootAnimation::Callbacks> createAnimationCallbacks() {
  return new AudioAnimationCallbacks();
}

}  // namespace audioplay
