// Copyright 2014 The Chromium 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 <stdlib.h>
#include <string.h>

#include <algorithm>
#include <limits>
#include <vector>

#include "ppapi/cpp/audio_buffer.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/logging.h"
#include "ppapi/cpp/media_stream_audio_track.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/size.h"
#include "ppapi/cpp/var_dictionary.h"
#include "ppapi/utility/completion_callback_factory.h"

// When compiling natively on Windows, PostMessage can be #define-d to
// something else.
#ifdef PostMessage
#undef PostMessage
#endif

// This example demonstrates receiving audio samples from an AndioMediaTrack
// and visualizing them.

namespace {

const uint32_t kColorRed = 0xFFFF0000;
const uint32_t kColorGreen = 0xFF00FF00;
const uint32_t kColorGrey1 = 0xFF202020;
const uint32_t kColorGrey2 = 0xFF404040;
const uint32_t kColorGrey3 = 0xFF606060;

class MediaStreamAudioInstance : public pp::Instance {
 public:
  explicit MediaStreamAudioInstance(PP_Instance instance)
      : pp::Instance(instance),
        callback_factory_(this),
        first_buffer_(true),
        sample_count_(0),
        channel_count_(0),
        timer_interval_(0),
        pending_paint_(false),
        waiting_for_flush_completion_(false) {
  }

  virtual ~MediaStreamAudioInstance() {
  }

  virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
    if (position.size() == size_)
      return;

    size_ = position.size();
    device_context_ = pp::Graphics2D(this, size_, false);
    if (!BindGraphics(device_context_))
      return;

    Paint();
  }

  virtual void HandleMessage(const pp::Var& var_message) {
    if (!var_message.is_dictionary())
      return;
    pp::VarDictionary var_dictionary_message(var_message);
    pp::Var var_track = var_dictionary_message.Get("track");
    if (!var_track.is_resource())
      return;

    pp::Resource resource_track = var_track.AsResource();
    audio_track_ = pp::MediaStreamAudioTrack(resource_track);
    audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
          &MediaStreamAudioInstance::OnGetBuffer));
  }

 private:
  void ScheduleNextTimer() {
    PP_DCHECK(timer_interval_ > 0);
    pp::Module::Get()->core()->CallOnMainThread(
        timer_interval_,
        callback_factory_.NewCallback(&MediaStreamAudioInstance::OnTimer),
        0);
  }

  void OnTimer(int32_t) {
    ScheduleNextTimer();
    Paint();
  }

  void DidFlush(int32_t result) {
    waiting_for_flush_completion_ = false;
    if (pending_paint_)
      Paint();
  }

  void Paint() {
    if (waiting_for_flush_completion_) {
      pending_paint_ = true;
      return;
    }

    pending_paint_ = false;

    if (size_.IsEmpty())
      return;  // Nothing to do.

    pp::ImageData image = PaintImage(size_);
    if (!image.is_null()) {
      device_context_.ReplaceContents(&image);
      waiting_for_flush_completion_ = true;
      device_context_.Flush(
          callback_factory_.NewCallback(&MediaStreamAudioInstance::DidFlush));
    }
  }

  pp::ImageData PaintImage(const pp::Size& size) {
    pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
    if (image.is_null())
      return image;

    // Clear to dark grey.
    for (int y = 0; y < size.height(); y++) {
      for (int x = 0; x < size.width(); x++)
        *image.GetAddr32(pp::Point(x, y)) = kColorGrey1;
    }

    int mid_height = size.height() / 2;
    int max_amplitude = size.height() * 4 / 10;

    // Draw some lines.
    for (int x = 0; x < size.width(); x++) {
      *image.GetAddr32(pp::Point(x, mid_height)) = kColorGrey3;
      *image.GetAddr32(pp::Point(x, mid_height + max_amplitude)) = kColorGrey2;
      *image.GetAddr32(pp::Point(x, mid_height - max_amplitude)) = kColorGrey2;
    }


    // Draw our samples.
    for (int x = 0, i = 0;
         x < std::min(size.width(), static_cast<int>(sample_count_));
         x++, i += channel_count_) {
      for (uint32_t ch = 0; ch < std::min(channel_count_, 2U); ++ch) {
        int y = samples_[i + ch] * max_amplitude /
                (std::numeric_limits<int16_t>::max() + 1) + mid_height;
        *image.GetAddr32(pp::Point(x, y)) = (ch == 0 ? kColorRed : kColorGreen);
      }
    }

    return image;
  }

  // Callback that is invoked when new buffers are received.
  void OnGetBuffer(int32_t result, pp::AudioBuffer buffer) {
    if (result != PP_OK)
      return;

    PP_DCHECK(buffer.GetSampleSize() == PP_AUDIOBUFFER_SAMPLESIZE_16_BITS);
    const char* data = static_cast<const char*>(buffer.GetDataBuffer());
    uint32_t channels = buffer.GetNumberOfChannels();
    uint32_t samples = buffer.GetNumberOfSamples() / channels;

    if (channel_count_ != channels || sample_count_ != samples) {
      channel_count_ = channels;
      sample_count_ = samples;

      samples_.resize(sample_count_ * channel_count_);
      timer_interval_ = (sample_count_ * 1000) / buffer.GetSampleRate() + 5;
      // Start the timer for the first buffer.
      if (first_buffer_) {
        first_buffer_ = false;
        ScheduleNextTimer();
      }
    }

    memcpy(samples_.data(), data,
        sample_count_ * channel_count_ * sizeof(int16_t));

    audio_track_.RecycleBuffer(buffer);
    audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
        &MediaStreamAudioInstance::OnGetBuffer));

  }

  pp::MediaStreamAudioTrack audio_track_;
  pp::CompletionCallbackFactory<MediaStreamAudioInstance> callback_factory_;

  bool first_buffer_;
  uint32_t sample_count_;
  uint32_t channel_count_;
  std::vector<int16_t> samples_;

  int32_t timer_interval_;

  // Painting stuff.
  pp::Size size_;
  pp::Graphics2D device_context_;
  bool pending_paint_;
  bool waiting_for_flush_completion_;
};

class MediaStreamAudioModule : public pp::Module {
 public:
  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new MediaStreamAudioInstance(instance);
  }
};

}  // namespace

namespace pp {

// Factory function for your specialization of the Module object.
Module* CreateModule() {
  return new MediaStreamAudioModule();
}

}  // namespace pp
