// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <audio-utils/audio-output.h>
#include <audio-utils/audio-stream.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <stdio.h>
#include <string.h>
#include <zircon/device/audio.h>

namespace audio {
namespace utils {

fbl::unique_ptr<AudioOutput> AudioOutput::Create(uint32_t dev_id) {
    fbl::AllocChecker ac;
    fbl::unique_ptr<AudioOutput> res(new (&ac) AudioOutput(dev_id));
    if (!ac.check())
        return nullptr;
    return res;
}

fbl::unique_ptr<AudioOutput> AudioOutput::Create(const char* dev_path) {
    fbl::AllocChecker ac;
    fbl::unique_ptr<AudioOutput> res(new (&ac) AudioOutput(dev_path));
    if (!ac.check())
        return nullptr;
    return res;
}

zx_status_t AudioOutput::Play(AudioSource& source) {
    zx_status_t res;

    if (source.finished())
        return ZX_OK;

    AudioSource::Format format;
    res = source.GetFormat(&format);
    if (res != ZX_OK) {
        printf("Failed to get source's format (res %d)\n", res);
        return res;
    }

    res = SetFormat(format.frame_rate, format.channels, format.sample_format);
    if (res != ZX_OK) {
        printf("Failed to set source format [%u Hz, %hu Chan, %08x fmt] (res %d)\n",
                format.frame_rate, format.channels, format.sample_format, res);
        return res;
    }

    // ALSA under QEMU required huge buffers.
    //
    // TODO(johngro) : Add the ability to determine what type of read-ahead the
    // HW is going to require so we can adjust our buffer size to what the HW
    // requires, not what ALSA under QEMU requires.
    res = GetBuffer(480 * 20 * 3, 3);
    if (res != ZX_OK) {
        printf("Failed to set output format (res %d)\n", res);
        return res;
    }

    memset(rb_virt_, 0, rb_sz_);

    auto buf = reinterpret_cast<uint8_t*>(rb_virt_);
    uint32_t rd, wr;
    uint32_t playout_rd, playout_amt;
    bool started = false;
    rd = wr = 0;
    playout_rd = playout_amt = 0;

    while (true) {
        uint32_t bytes_read, junk;
        audio_rb_position_notify_t pos_notif;
        zx_signals_t sigs;

        // Top up the buffer.  In theory, we should only need to loop 2 times in
        // order to handle a ring discontinuity
        for (uint32_t i = 0; i < 2; ++i) {
            uint32_t space = (rb_sz_ + rd - wr - 1) % rb_sz_;
            uint32_t todo  = fbl::min(space, rb_sz_ - wr);
            ZX_DEBUG_ASSERT(space < rb_sz_);

            if (!todo)
                break;

            if (source.finished()) {
                memset(buf + wr, 0, todo);
                zx_cache_flush(buf + wr, todo, ZX_CACHE_FLUSH_DATA);

                wr += todo;
            } else {
                uint32_t done;
                res = source.GetFrames(buf + wr, fbl::min(space, rb_sz_ - wr), &done);
                if (res != ZX_OK) {
                    printf("Error packing frames (res %d)\n", res);
                    break;
                }
                zx_cache_flush(buf + wr, done, ZX_CACHE_FLUSH_DATA);
                wr += done;

                if (source.finished()) {
                    playout_rd  = rd;
                    playout_amt = (rb_sz_ + wr - rd) % rb_sz_;

                    // We have just become finished.  Reset the loop counter and
                    // start over, this time filling with as much silence as we
                    // can.
                    i = 0;
                }
            }

            if (wr < rb_sz_)
                break;

            ZX_DEBUG_ASSERT(wr == rb_sz_);
            wr = 0;
        }

        if (res != ZX_OK)
            break;

        // If we have not started yet, do so.
        if (!started) {
            res = StartRingBuffer();
            if (res != ZX_OK) {
                printf("Failed to start ring buffer!\n");
                break;
            }
            started = true;
        }

        res = rb_ch_.wait_one(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
                              zx::time::infinite(), &sigs);

        if (res != ZX_OK) {
            printf("Failed to wait for notificiation (res %d)\n", res);
            break;
        }

        if (sigs & ZX_CHANNEL_PEER_CLOSED) {
            printf("Peer closed connection during playback!\n");
            break;
        }

        res = rb_ch_.read(0,
                          &pos_notif, nullptr, sizeof(pos_notif), 0,
                          &bytes_read, &junk);
        if (res != ZX_OK) {
            printf("Failed to read notification from ring buffer channel (res %d)\n", res);
            break;
        }

        if (bytes_read != sizeof(pos_notif)) {
            printf("Bad size when reading notification from ring buffer channel (%u != %zu)\n",
                   bytes_read, sizeof(pos_notif));
            res = ZX_ERR_INTERNAL;
            break;
        }

        if (pos_notif.hdr.cmd != AUDIO_RB_POSITION_NOTIFY) {
            printf("Unexpected command type when reading notification from ring "
                   "buffer channel (cmd %04x)\n", pos_notif.hdr.cmd);
            res = ZX_ERR_INTERNAL;
            break;
        }

        rd = pos_notif.ring_buffer_pos;

        // rd has moved.  If the source has finished and rd has moved at least
        // the playout distance, we are finsihed.
        if (source.finished()) {
            uint32_t dist = (rb_sz_ + rd - playout_rd) % rb_sz_;

            if (dist >= playout_amt)
                break;

            playout_amt -= dist;
            playout_rd   = rd;
        }
    }

    if (res == ZX_OK) {
        // We have already let the DMA engine catch up, but we still need to
        // wait for the fifo to play out.  For now, just hard code this as
        // 30uSec.
        //
        // TODO: base this on the start time and the number of frames queued
        // instead of just making a number up.
        zx_nanosleep(zx_deadline_after(ZX_MSEC(30)));
    }

    zx_status_t stop_res = StopRingBuffer();
    if (res == ZX_OK)
        res = stop_res;

    return res;
}

}  // namespace utils
}  // namespace audio
