This source file includes following definitions.
- AddInput
 
- RemoveInput
 
- ProvideInput
 
- fake_consumer_
 
- Open
 
- Start
 
- Stop
 
- AddOutputStream
 
- RemoveOutputStream
 
- PumpAudio
 
- Close
 
- GetMaxVolume
 
- SetVolume
 
- GetVolume
 
- SetAutomaticGainControl
 
- GetAutomaticGainControl
 
#include "media/audio/virtual_audio_input_stream.h"
#include <algorithm>
#include <utility>
#include "base/bind.h"
#include "base/single_thread_task_runner.h"
#include "media/audio/virtual_audio_output_stream.h"
namespace media {
class LoopbackAudioConverter : public AudioConverter::InputCallback {
 public:
  LoopbackAudioConverter(const AudioParameters& input_params,
                         const AudioParameters& output_params)
      : audio_converter_(input_params, output_params, false) {}
  virtual ~LoopbackAudioConverter() {}
  void AddInput(AudioConverter::InputCallback* input) {
    audio_converter_.AddInput(input);
  }
  void RemoveInput(AudioConverter::InputCallback* input) {
    audio_converter_.RemoveInput(input);
  }
 private:
  virtual double ProvideInput(AudioBus* audio_bus,
                              base::TimeDelta buffer_delay) OVERRIDE {
    audio_converter_.Convert(audio_bus);
    return 1.0;
  }
  AudioConverter audio_converter_;
  DISALLOW_COPY_AND_ASSIGN(LoopbackAudioConverter);
};
VirtualAudioInputStream::VirtualAudioInputStream(
    const AudioParameters& params,
    const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner,
    const AfterCloseCallback& after_close_cb)
    : worker_task_runner_(worker_task_runner),
      after_close_cb_(after_close_cb),
      callback_(NULL),
      buffer_(new uint8[params.GetBytesPerBuffer()]),
      params_(params),
      mixer_(params_, params_, false),
      num_attached_output_streams_(0),
      fake_consumer_(worker_task_runner_, params_) {
  DCHECK(params_.IsValid());
  DCHECK(worker_task_runner_.get());
  
  
  thread_checker_.DetachFromThread();
}
VirtualAudioInputStream::~VirtualAudioInputStream() {
  DCHECK(!callback_);
  
  
  DCHECK_EQ(0, num_attached_output_streams_);
  for (AudioConvertersMap::iterator it = converters_.begin();
       it != converters_.end(); ++it) {
    delete it->second;
  }
}
bool VirtualAudioInputStream::Open() {
  DCHECK(thread_checker_.CalledOnValidThread());
  memset(buffer_.get(), 0, params_.GetBytesPerBuffer());
  return true;
}
void VirtualAudioInputStream::Start(AudioInputCallback* callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  callback_ = callback;
  fake_consumer_.Start(base::Bind(
      &VirtualAudioInputStream::PumpAudio, base::Unretained(this)));
}
void VirtualAudioInputStream::Stop() {
  DCHECK(thread_checker_.CalledOnValidThread());
  fake_consumer_.Stop();
  callback_ = NULL;
}
void VirtualAudioInputStream::AddOutputStream(
    VirtualAudioOutputStream* stream, const AudioParameters& output_params) {
  DCHECK(thread_checker_.CalledOnValidThread());
  base::AutoLock scoped_lock(converter_network_lock_);
  AudioConvertersMap::iterator converter = converters_.find(output_params);
  if (converter == converters_.end()) {
    std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert(
        std::make_pair(output_params,
                       new LoopbackAudioConverter(output_params, params_)));
    converter = result.first;
    
    mixer_.AddInput(converter->second);
  }
  converter->second->AddInput(stream);
  ++num_attached_output_streams_;
}
void VirtualAudioInputStream::RemoveOutputStream(
    VirtualAudioOutputStream* stream, const AudioParameters& output_params) {
  DCHECK(thread_checker_.CalledOnValidThread());
  base::AutoLock scoped_lock(converter_network_lock_);
  DCHECK(converters_.find(output_params) != converters_.end());
  converters_[output_params]->RemoveInput(stream);
  --num_attached_output_streams_;
  DCHECK_LE(0, num_attached_output_streams_);
}
void VirtualAudioInputStream::PumpAudio(AudioBus* audio_bus) {
  DCHECK(worker_task_runner_->BelongsToCurrentThread());
  {
    base::AutoLock scoped_lock(converter_network_lock_);
    mixer_.Convert(audio_bus);
  }
  audio_bus->ToInterleaved(params_.frames_per_buffer(),
                           params_.bits_per_sample() / 8,
                           buffer_.get());
  callback_->OnData(this,
                    buffer_.get(),
                    params_.GetBytesPerBuffer(),
                    params_.GetBytesPerBuffer(),
                    1.0);
}
void VirtualAudioInputStream::Close() {
  DCHECK(thread_checker_.CalledOnValidThread());
  Stop();  
  
  
  
  if (!after_close_cb_.is_null()) {
    const AfterCloseCallback cb = after_close_cb_;
    after_close_cb_.Reset();
    cb.Run(this);
  }
}
double VirtualAudioInputStream::GetMaxVolume() {
  return 1.0;
}
void VirtualAudioInputStream::SetVolume(double volume) {}
double VirtualAudioInputStream::GetVolume() {
  return 1.0;
}
void VirtualAudioInputStream::SetAutomaticGainControl(bool enabled) {}
bool VirtualAudioInputStream::GetAutomaticGainControl() {
  return false;
}
}