// Copyright 2018 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 "garnet/examples/media/simple_sine/simple_sine.h"

#include "lib/async-loop/cpp/loop.h"
#include "lib/fxl/logging.h"

namespace {
// Set the AudioRenderer stream type to: 48 kHz, mono, 32-bit float.
constexpr float kFrameRate = 48000.0f;

// This example feeds the system 1 second of audio, in 10-millisecond payloads.
constexpr size_t kNumPayloads = 100;
constexpr size_t kFramesPerPayload = kFrameRate / kNumPayloads;

// Play a 439 Hz sine wave at 1/8 of full-scale volume.
constexpr double kFrequency = 439.0;
constexpr double kAmplitude = 0.125;
}  // namespace

namespace examples {

MediaApp::MediaApp(fit::closure quit_callback)
    : quit_callback_(std::move(quit_callback)) {
  FXL_DCHECK(quit_callback_);
}

// Prepare for playback, submit initial data and start the presentation timeline
void MediaApp::Run(component::StartupContext* app_context) {
  AcquireAudioRenderer(app_context);
  SetStreamType();

  if (CreateMemoryMapping() != ZX_OK) {
    Shutdown();
    return;
  }

  WriteAudioIntoBuffer();
  for (size_t payload_num = 0; payload_num < kNumPayloads; ++payload_num) {
    SendPacket(CreatePacket(payload_num));
  }

  // By not explicitly setting timestamp values for reference clock or media
  // clock, we indicate that we want to start playback, with default timing.
  // I.e., at a system reference_time of "as soon as safely possible", we will
  // present audio corresponding to an initial media_time (PTS) of zero.
  //
  // AudioRenderer defaults to unity gain, unmuted; we need not change our
  // volume. (Although not shown here, we would do so via the GainControl
  // interface.)
  audio_renderer_->PlayNoReply(fuchsia::media::NO_TIMESTAMP,
                               fuchsia::media::NO_TIMESTAMP);
}

// Use StartupContext to acquire AudioPtr, which we only need in order to get
// an AudioRendererPtr. Set an error handler, in case of channel closure.
void MediaApp::AcquireAudioRenderer(component::StartupContext* app_context) {
  fuchsia::media::AudioPtr audio =
      app_context->ConnectToEnvironmentService<fuchsia::media::Audio>();

  audio->CreateAudioRenderer(audio_renderer_.NewRequest());

  audio_renderer_.set_error_handler([this](zx_status_t status) {
    FXL_LOG(ERROR)
        << "fuchsia::media::AudioRenderer connection lost. Quitting.";
    Shutdown();
  });
}

// Set the AudioRenderer's audio stream_type: mono 48kHz 32-bit float.
void MediaApp::SetStreamType() {
  FXL_DCHECK(audio_renderer_);

  fuchsia::media::AudioStreamType stream_type;

  stream_type.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
  stream_type.channels = 1;
  stream_type.frames_per_second = kFrameRate;

  audio_renderer_->SetPcmStreamType(std::move(stream_type));
}

// Create a Virtual Memory Object, and map enough memory for audio buffers.
// Send a reduced-rights handle to AudioRenderer to act as a shared buffer.
zx_status_t MediaApp::CreateMemoryMapping() {
  zx::vmo payload_vmo;

  payload_size_ = kFramesPerPayload * sizeof(float);
  total_mapping_size_ = payload_size_ * kNumPayloads;

  zx_status_t status = payload_buffer_.CreateAndMap(
      total_mapping_size_, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr,
      &payload_vmo, ZX_RIGHT_READ | ZX_RIGHT_MAP | ZX_RIGHT_TRANSFER);

  if (status != ZX_OK) {
    FXL_LOG(ERROR) << "VmoMapper:::CreateAndMap failed - " << status;
    return status;
  }

  audio_renderer_->AddPayloadBuffer(0, std::move(payload_vmo));

  return ZX_OK;
}

// Write a sine wave into our buffer; we'll submit packets that point to it.
void MediaApp::WriteAudioIntoBuffer() {
  float* float_buffer = reinterpret_cast<float*>(payload_buffer_.start());

  for (size_t frame = 0; frame < kFramesPerPayload * kNumPayloads; ++frame) {
    float_buffer[frame] =
        kAmplitude * sin(frame * kFrequency * 2 * M_PI / kFrameRate);
  }
}

// We divide our cross-proc buffer into different zones, called payloads.
// Create a packet that corresponds to this particular payload.
// By specifying NO_TIMESTAMP for each packet's presentation timestamp, we rely
// on the AudioRenderer to treat the sequence of packets as a contiguous
// unbroken stream of audio. We just need to make sure we present packets early
// enough, and for this example we actually submit all packets before starting
// playback.
fuchsia::media::StreamPacket MediaApp::CreatePacket(size_t payload_num) {
  fuchsia::media::StreamPacket packet;

  // leave packet.pts as the default (fuchsia::media::NO_TIMESTAMP)
  // leave packet.payload_buffer_id as default (0): we only map a single buffer

  packet.payload_offset = (payload_num * payload_size_) % total_mapping_size_;
  packet.payload_size = payload_size_;
  return packet;
}

// Submit a packet, incrementing our count of packets sent. When it returns:
// a. if there are more packets to send, create and send the next packet;
// b. if all expected packets have completed, begin closing down the system.
void MediaApp::SendPacket(fuchsia::media::StreamPacket packet) {
  ++num_packets_sent_;
  audio_renderer_->SendPacket(std::move(packet),
                              [this]() { OnSendPacketComplete(); });
}

void MediaApp::OnSendPacketComplete() {
  ++num_packets_completed_;
  FXL_DCHECK(num_packets_completed_ <= kNumPayloads);

  if (num_packets_sent_ < kNumPayloads) {
    SendPacket(CreatePacket(num_packets_sent_));
  } else if (num_packets_completed_ >= kNumPayloads) {
    Shutdown();
  }
}

// Unmap memory, quit message loop (FIDL interfaces auto-delete upon ~MediaApp).
void MediaApp::Shutdown() {
  payload_buffer_.Unmap();
  quit_callback_();
}

}  // namespace examples

int main(int argc, const char** argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToThread);
  auto startup_context = component::StartupContext::CreateFromStartupInfo();

  examples::MediaApp media_app([&loop]() {
    async::PostTask(loop.dispatcher(), [&loop]() { loop.Quit(); });
  });

  media_app.Run(startup_context.get());

  loop.Run();  // Now wait for the message loop to return...

  return 0;
}
