1 // Copyright 2013 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.
5 #include "media/audio/sounds/audio_stream_handler.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "media/audio/audio_manager.h"
12 #include "media/audio/audio_manager_base.h"
13 #include "media/base/channel_layout.h"
20 const double kOutputVolumePercent = 0.8;
22 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL;
23 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL;
27 class AudioStreamHandler::AudioStreamContainer
28 : public AudioOutputStream::AudioSourceCallback {
30 AudioStreamContainer(const WavAudioHandler& wav_audio,
31 const AudioParameters& params)
33 wav_audio_(wav_audio),
38 virtual ~AudioStreamContainer() {
39 DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread());
43 DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread());
46 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params_,
49 if (!stream_ || !stream_->Open()) {
50 LOG(ERROR) << "Failed to open an output stream.";
53 stream_->SetVolume(kOutputVolumePercent);
55 // TODO (ygorshenin@): implement smart stream rewind.
60 if (g_audio_source_for_testing)
61 stream_->Start(g_audio_source_for_testing);
65 if (g_observer_for_testing)
66 g_observer_for_testing->OnPlay();
70 DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread());
77 if (g_observer_for_testing)
78 g_observer_for_testing->OnStop(cursor_);
82 // AudioOutputStream::AudioSourceCallback overrides:
83 // Following methods could be called from *ANY* thread.
84 virtual int OnMoreData(AudioBus* dest,
85 AudioBuffersState /* state */) OVERRIDE {
86 size_t bytes_written = 0;
87 if (wav_audio_.AtEnd(cursor_) ||
88 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) {
89 AudioManager::Get()->GetMessageLoop()->PostTask(
91 base::Bind(&AudioStreamContainer::Stop, base::Unretained(this)));
94 cursor_ += bytes_written;
96 return dest->frames();
99 virtual int OnMoreIOData(AudioBus* /* source */,
101 AudioBuffersState state) OVERRIDE {
102 return OnMoreData(dest, state);
105 virtual void OnError(AudioOutputStream* /* stream */) OVERRIDE {
106 LOG(ERROR) << "Error during system sound reproduction.";
109 AudioOutputStream* stream_;
111 const WavAudioHandler wav_audio_;
112 const AudioParameters params_;
116 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer);
119 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data)
120 : wav_audio_(wav_data),
121 initialized_(false) {
122 AudioManager* manager = AudioManager::Get();
124 LOG(ERROR) << "Can't get access to audio manager.";
127 AudioParameters params(
128 AudioParameters::AUDIO_PCM_LOW_LATENCY,
129 GuessChannelLayout(wav_audio_.num_channels()),
130 wav_audio_.sample_rate(),
131 wav_audio_.bits_per_sample(),
132 manager->GetDefaultOutputStreamParameters().frames_per_buffer());
133 if (!params.IsValid()) {
134 LOG(ERROR) << "Audio params are invalid.";
137 stream_.reset(new AudioStreamContainer(wav_audio_, params));
141 AudioStreamHandler::~AudioStreamHandler() {
142 DCHECK(CalledOnValidThread());
143 AudioManager::Get()->GetMessageLoop()->PostTask(
145 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get())));
146 AudioManager::Get()->GetMessageLoop()->DeleteSoon(FROM_HERE,
150 bool AudioStreamHandler::IsInitialized() const {
151 DCHECK(CalledOnValidThread());
155 bool AudioStreamHandler::Play() {
156 DCHECK(CalledOnValidThread());
158 if (!IsInitialized())
161 AudioManager::Get()->GetMessageLoop()->PostTask(
163 base::Bind(base::IgnoreResult(&AudioStreamContainer::Play),
164 base::Unretained(stream_.get())));
168 void AudioStreamHandler::Stop() {
169 DCHECK(CalledOnValidThread());
170 AudioManager::Get()->GetMessageLoop()->PostTask(
172 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get())));
176 void AudioStreamHandler::SetObserverForTesting(TestObserver* observer) {
177 g_observer_for_testing = observer;
181 void AudioStreamHandler::SetAudioSourceForTesting(
182 AudioOutputStream::AudioSourceCallback* source) {
183 g_audio_source_for_testing = source;