15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdlib.h>
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string.h>
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <algorithm>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <limits>
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <vector>
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/audio_buffer.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/graphics_2d.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/image_data.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/instance.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/logging.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/media_stream_audio_track.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/module.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/rect.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/cpp/size.h"
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ppapi/cpp/var_dictionary.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// When compiling natively on Windows, PostMessage can be #define-d to
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// something else.
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef PostMessage
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#undef PostMessage
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This example demonstrates receiving audio samples from an AndioMediaTrack
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// and visualizing them.
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const uint32_t kColorRed = 0xFFFF0000;
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const uint32_t kColorGreen = 0xFF00FF00;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const uint32_t kColorGrey1 = 0xFF202020;
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const uint32_t kColorGrey2 = 0xFF404040;
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const uint32_t kColorGrey3 = 0xFF606060;
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MediaStreamAudioInstance : public pp::Instance {
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit MediaStreamAudioInstance(PP_Instance instance)
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : pp::Instance(instance),
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        callback_factory_(this),
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        first_buffer_(true),
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sample_count_(0),
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        channel_count_(0),
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        timer_interval_(0),
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        pending_paint_(false),
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        waiting_for_flush_completion_(false) {
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~MediaStreamAudioInstance() {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (position.size() == size_)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_ = position.size();
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    device_context_ = pp::Graphics2D(this, size_, false);
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!BindGraphics(device_context_))
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Paint();
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void HandleMessage(const pp::Var& var_message) {
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!var_message.is_dictionary())
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::VarDictionary var_dictionary_message(var_message);
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::Var var_track = var_dictionary_message.Get("track");
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!var_track.is_resource())
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::Resource resource_track = var_track.AsResource();
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_track_ = pp::MediaStreamAudioTrack(resource_track);
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &MediaStreamAudioInstance::OnGetBuffer));
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ScheduleNextTimer() {
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_DCHECK(timer_interval_ > 0);
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::Module::Get()->core()->CallOnMainThread(
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        timer_interval_,
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        callback_factory_.NewCallback(&MediaStreamAudioInstance::OnTimer),
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        0);
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnTimer(int32_t) {
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ScheduleNextTimer();
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Paint();
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void DidFlush(int32_t result) {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    waiting_for_flush_completion_ = false;
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (pending_paint_)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Paint();
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Paint() {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (waiting_for_flush_completion_) {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pending_paint_ = true;
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_paint_ = false;
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (size_.IsEmpty())
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;  // Nothing to do.
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::ImageData image = PaintImage(size_);
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!image.is_null()) {
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_context_.ReplaceContents(&image);
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      waiting_for_flush_completion_ = true;
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_context_.Flush(
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          callback_factory_.NewCallback(&MediaStreamAudioInstance::DidFlush));
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::ImageData PaintImage(const pp::Size& size) {
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (image.is_null())
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return image;
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Clear to dark grey.
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int y = 0; y < size.height(); y++) {
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (int x = 0; x < size.width(); x++)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        *image.GetAddr32(pp::Point(x, y)) = kColorGrey1;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int mid_height = size.height() / 2;
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int max_amplitude = size.height() * 4 / 10;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Draw some lines.
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int x = 0; x < size.width(); x++) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *image.GetAddr32(pp::Point(x, mid_height)) = kColorGrey3;
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *image.GetAddr32(pp::Point(x, mid_height + max_amplitude)) = kColorGrey2;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *image.GetAddr32(pp::Point(x, mid_height - max_amplitude)) = kColorGrey2;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Draw our samples.
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int x = 0, i = 0;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         x < std::min(size.width(), static_cast<int>(sample_count_));
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         x++, i += channel_count_) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (uint32_t ch = 0; ch < std::min(channel_count_, 2U); ++ch) {
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        int y = samples_[i + ch] * max_amplitude /
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                (std::numeric_limits<int16_t>::max() + 1) + mid_height;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        *image.GetAddr32(pp::Point(x, y)) = (ch == 0 ? kColorRed : kColorGreen);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return image;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Callback that is invoked when new buffers are received.
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnGetBuffer(int32_t result, pp::AudioBuffer buffer) {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (result != PP_OK)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_DCHECK(buffer.GetSampleSize() == PP_AUDIOBUFFER_SAMPLESIZE_16_BITS);
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* data = static_cast<const char*>(buffer.GetDataBuffer());
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint32_t channels = buffer.GetNumberOfChannels();
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint32_t samples = buffer.GetNumberOfSamples() / channels;
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (channel_count_ != channels || sample_count_ != samples) {
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      channel_count_ = channels;
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      sample_count_ = samples;
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      samples_.resize(sample_count_ * channel_count_);
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      timer_interval_ = (sample_count_ * 1000) / buffer.GetSampleRate() + 5;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Start the timer for the first buffer.
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (first_buffer_) {
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        first_buffer_ = false;
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ScheduleNextTimer();
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    memcpy(samples_.data(), data,
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sample_count_ * channel_count_ * sizeof(int16_t));
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_track_.RecycleBuffer(buffer);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &MediaStreamAudioInstance::OnGetBuffer));
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::MediaStreamAudioTrack audio_track_;
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::CompletionCallbackFactory<MediaStreamAudioInstance> callback_factory_;
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool first_buffer_;
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t sample_count_;
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t channel_count_;
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<int16_t> samples_;
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int32_t timer_interval_;
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Painting stuff.
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::Size size_;
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pp::Graphics2D device_context_;
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool pending_paint_;
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool waiting_for_flush_completion_;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MediaStreamAudioModule : public pp::Module {
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual pp::Instance* CreateInstance(PP_Instance instance) {
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return new MediaStreamAudioInstance(instance);
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace pp {
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Factory function for your specialization of the Module object.
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Module* CreateModule() {
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new MediaStreamAudioModule();
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace pp
225