OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/audio/audio_input_controller.h" | 5 #include "media/audio/audio_input_controller.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/threading/thread_restrictions.h" | 8 #include "base/threading/thread_restrictions.h" |
9 #include "media/base/limits.h" | 9 #include "media/base/limits.h" |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... | |
21 AudioInputController::AudioInputController(EventHandler* handler, | 21 AudioInputController::AudioInputController(EventHandler* handler, |
22 SyncWriter* sync_writer) | 22 SyncWriter* sync_writer) |
23 : creator_loop_(base::MessageLoopProxy::current()), | 23 : creator_loop_(base::MessageLoopProxy::current()), |
24 handler_(handler), | 24 handler_(handler), |
25 stream_(NULL), | 25 stream_(NULL), |
26 ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE, | 26 ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE, |
27 base::TimeDelta::FromSeconds(kTimerResetInterval), | 27 base::TimeDelta::FromSeconds(kTimerResetInterval), |
28 this, | 28 this, |
29 &AudioInputController::DoReportNoDataError)), | 29 &AudioInputController::DoReportNoDataError)), |
30 state_(kEmpty), | 30 state_(kEmpty), |
31 sync_writer_(sync_writer) { | 31 sync_writer_(sync_writer), |
32 max_volume_(0.0) { | |
32 DCHECK(creator_loop_); | 33 DCHECK(creator_loop_); |
33 } | 34 } |
34 | 35 |
35 AudioInputController::~AudioInputController() { | 36 AudioInputController::~AudioInputController() { |
36 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); | 37 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); |
37 } | 38 } |
38 | 39 |
39 // static | 40 // static |
40 scoped_refptr<AudioInputController> AudioInputController::Create( | 41 scoped_refptr<AudioInputController> AudioInputController::Create( |
41 AudioManager* audio_manager, | 42 AudioManager* audio_manager, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
100 message_loop_->PostTask(FROM_HERE, base::Bind( | 101 message_loop_->PostTask(FROM_HERE, base::Bind( |
101 &AudioInputController::DoRecord, this)); | 102 &AudioInputController::DoRecord, this)); |
102 } | 103 } |
103 | 104 |
104 void AudioInputController::Close(const base::Closure& closed_task) { | 105 void AudioInputController::Close(const base::Closure& closed_task) { |
105 DCHECK(!closed_task.is_null()); | 106 DCHECK(!closed_task.is_null()); |
106 message_loop_->PostTask(FROM_HERE, base::Bind( | 107 message_loop_->PostTask(FROM_HERE, base::Bind( |
107 &AudioInputController::DoClose, this, closed_task)); | 108 &AudioInputController::DoClose, this, closed_task)); |
108 } | 109 } |
109 | 110 |
111 void AudioInputController::SetVolume(double volume) { | |
112 message_loop_->PostTask(FROM_HERE, base::Bind( | |
113 &AudioInputController::DoSetVolume, this, volume)); | |
114 } | |
115 | |
116 void AudioInputController::SetAutomaticGainControl(bool enabled) { | |
117 message_loop_->PostTask(FROM_HERE, base::Bind( | |
118 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); | |
119 } | |
120 | |
110 void AudioInputController::DoCreate(AudioManager* audio_manager, | 121 void AudioInputController::DoCreate(AudioManager* audio_manager, |
111 const AudioParameters& params, | 122 const AudioParameters& params, |
112 const std::string& device_id) { | 123 const std::string& device_id) { |
113 DCHECK(message_loop_->BelongsToCurrentThread()); | 124 DCHECK(message_loop_->BelongsToCurrentThread()); |
114 | 125 |
115 stream_ = audio_manager->MakeAudioInputStream(params, device_id); | 126 stream_ = audio_manager->MakeAudioInputStream(params, device_id); |
116 | 127 |
117 if (!stream_) { | 128 if (!stream_) { |
118 // TODO(satish): Define error types. | 129 // TODO(satish): Define error types. |
119 handler_->OnError(this, 0); | 130 handler_->OnError(this, 0); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 } | 175 } |
165 | 176 |
166 closed_task.Run(); | 177 closed_task.Run(); |
167 } | 178 } |
168 | 179 |
169 void AudioInputController::DoReportError(int code) { | 180 void AudioInputController::DoReportError(int code) { |
170 DCHECK(message_loop_->BelongsToCurrentThread()); | 181 DCHECK(message_loop_->BelongsToCurrentThread()); |
171 handler_->OnError(this, code); | 182 handler_->OnError(this, code); |
172 } | 183 } |
173 | 184 |
185 void AudioInputController::DoSetVolume(double volume) { | |
186 DCHECK(message_loop_->BelongsToCurrentThread()); | |
187 DCHECK(volume >= 0 && volume <= 1.0); | |
scherkus (not reviewing)
2012/03/20 13:49:41
nit: if you split these DCHECKs into DCHECK_GE() a
henrika (OOO until Aug 14)
2012/03/21 10:16:04
Nice. Thanks.
| |
188 | |
189 if (state_ != kCreated && state_ != kRecording) | |
190 return; | |
191 | |
192 // Only ask for the maximum volume at first call and use cached value | |
193 // for remaining function calls. | |
194 if (!max_volume_) { | |
195 max_volume_ = stream_->GetMaxVolume(); | |
196 } | |
197 | |
198 if (max_volume_ == 0.0) { | |
199 DLOG(WARNING) << "Failed to access input volume control"; | |
200 return; | |
201 } | |
202 | |
203 // Set the stream volume and scale to a range matched to the platform. | |
204 stream_->SetVolume(max_volume_ * volume); | |
205 } | |
206 | |
207 void AudioInputController::DoSetAutomaticGainControl(bool enabled) { | |
208 DCHECK(message_loop_->BelongsToCurrentThread()); | |
209 | |
210 if (state_ != kCreated) | |
211 return; | |
212 | |
213 stream_->SetAutomaticGainControl(enabled); | |
214 } | |
215 | |
174 void AudioInputController::DoReportNoDataError() { | 216 void AudioInputController::DoReportNoDataError() { |
175 DCHECK(creator_loop_->BelongsToCurrentThread()); | 217 DCHECK(creator_loop_->BelongsToCurrentThread()); |
176 | 218 |
177 // Error notifications should be sent on the audio-manager thread. | 219 // Error notifications should be sent on the audio-manager thread. |
178 int code = 0; | 220 int code = 0; |
179 message_loop_->PostTask(FROM_HERE, base::Bind( | 221 message_loop_->PostTask(FROM_HERE, base::Bind( |
180 &AudioInputController::DoReportError, this, code)); | 222 &AudioInputController::DoReportError, this, code)); |
181 } | 223 } |
182 | 224 |
183 void AudioInputController::DoResetNoDataTimer() { | 225 void AudioInputController::DoResetNoDataTimer() { |
184 DCHECK(creator_loop_->BelongsToCurrentThread()); | 226 DCHECK(creator_loop_->BelongsToCurrentThread()); |
185 no_data_timer_.Reset(); | 227 no_data_timer_.Reset(); |
186 } | 228 } |
187 | 229 |
188 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, | 230 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, |
189 uint32 size, uint32 hardware_delay_bytes) { | 231 uint32 size, uint32 hardware_delay_bytes, |
232 double volume) { | |
190 { | 233 { |
191 base::AutoLock auto_lock(lock_); | 234 base::AutoLock auto_lock(lock_); |
192 if (state_ != kRecording) | 235 if (state_ != kRecording) |
193 return; | 236 return; |
194 } | 237 } |
195 | 238 |
196 creator_loop_->PostTask(FROM_HERE, base::Bind( | 239 creator_loop_->PostTask(FROM_HERE, base::Bind( |
197 &AudioInputController::DoResetNoDataTimer, this)); | 240 &AudioInputController::DoResetNoDataTimer, this)); |
198 | 241 |
199 // Use SyncSocket if we are in a low-latency mode. | 242 // Use SyncSocket if we are in a low-latency mode. |
200 if (LowLatencyMode()) { | 243 if (LowLatencyMode()) { |
201 sync_writer_->Write(data, size); | 244 sync_writer_->Write(data, size, volume); |
202 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); | 245 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); |
203 return; | 246 return; |
204 } | 247 } |
205 | 248 |
206 handler_->OnData(this, data, size); | 249 handler_->OnData(this, data, size); |
207 } | 250 } |
208 | 251 |
209 void AudioInputController::OnClose(AudioInputStream* stream) { | 252 void AudioInputController::OnClose(AudioInputStream* stream) { |
210 DVLOG(1) << "AudioInputController::OnClose()"; | 253 DVLOG(1) << "AudioInputController::OnClose()"; |
211 // TODO(satish): Sometimes the device driver closes the input stream without | 254 // TODO(satish): Sometimes the device driver closes the input stream without |
(...skipping 17 matching lines...) Expand all Loading... | |
229 stream_->Close(); | 272 stream_->Close(); |
230 stream_ = NULL; | 273 stream_ = NULL; |
231 } | 274 } |
232 | 275 |
233 // Should be last in the method, do not touch "this" from here on. | 276 // Should be last in the method, do not touch "this" from here on. |
234 if (done != NULL) | 277 if (done != NULL) |
235 done->Signal(); | 278 done->Signal(); |
236 } | 279 } |
237 | 280 |
238 } // namespace media | 281 } // namespace media |
OLD | NEW |