1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "media/audio/virtual_audio_output_stream.h"
6
7#include "base/logging.h"
8#include "media/audio/virtual_audio_input_stream.h"
9
10namespace media {
11
12VirtualAudioOutputStream::VirtualAudioOutputStream(
13    const AudioParameters& params, VirtualAudioInputStream* target,
14    const AfterCloseCallback& after_close_cb)
15    : params_(params), target_input_stream_(target),
16      after_close_cb_(after_close_cb), callback_(NULL), volume_(1.0f) {
17  DCHECK(params_.IsValid());
18  DCHECK(target);
19
20  // VAOS can be constructed on any thread, but will DCHECK that all
21  // AudioOutputStream methods are called from the same thread.
22  thread_checker_.DetachFromThread();
23}
24
25VirtualAudioOutputStream::~VirtualAudioOutputStream() {
26  DCHECK(!callback_);
27}
28
29bool VirtualAudioOutputStream::Open() {
30  DCHECK(thread_checker_.CalledOnValidThread());
31  return true;
32}
33
34void VirtualAudioOutputStream::Start(AudioSourceCallback* callback)  {
35  DCHECK(thread_checker_.CalledOnValidThread());
36  DCHECK(!callback_);
37  callback_ = callback;
38  target_input_stream_->AddOutputStream(this, params_);
39}
40
41void VirtualAudioOutputStream::Stop() {
42  DCHECK(thread_checker_.CalledOnValidThread());
43  if (callback_) {
44    target_input_stream_->RemoveOutputStream(this, params_);
45    callback_ = NULL;
46  }
47}
48
49void VirtualAudioOutputStream::Close() {
50  DCHECK(thread_checker_.CalledOnValidThread());
51
52  Stop();
53
54  // If a non-null AfterCloseCallback was provided to the constructor, invoke it
55  // here.  The callback is moved to a stack-local first since |this| could be
56  // destroyed during Run().
57  if (!after_close_cb_.is_null()) {
58    const AfterCloseCallback cb = after_close_cb_;
59    after_close_cb_.Reset();
60    cb.Run(this);
61  }
62}
63
64void VirtualAudioOutputStream::SetVolume(double volume) {
65  DCHECK(thread_checker_.CalledOnValidThread());
66  volume_ = volume;
67}
68
69void VirtualAudioOutputStream::GetVolume(double* volume) {
70  DCHECK(thread_checker_.CalledOnValidThread());
71  *volume = volume_;
72}
73
74double VirtualAudioOutputStream::ProvideInput(AudioBus* audio_bus,
75                                              base::TimeDelta buffer_delay) {
76  // Note: This method may be invoked on any one thread, depending on the
77  // platform.
78  DCHECK(callback_);
79
80  const int frames = callback_->OnMoreData(audio_bus, AudioBuffersState());
81  if (frames < audio_bus->frames())
82    audio_bus->ZeroFramesPartial(frames, audio_bus->frames() - frames);
83
84  return frames > 0 ? volume_ : 0;
85}
86
87}  // namespace media
88